Let observer refusals reach the caller on update and bulk delete - #259
Merged
roncodes merged 2 commits intoSep 16, 2026
Merged
Conversation
An observer that refuses a write by throwing FleetbaseRequestValidationException had its explanation discarded on two paths. The write was still refused, but the caller saw "Invalid request" or "Error occurred while trying to update a X" instead of the message the observer wrote. Both sites already had a handler for the exception; each was made unreachable by a catch block one frame deeper. updateRecordFromRequest() wrapped every exception from $record->update() in a plain \Exception, so the controller's dedicated catch and the global handler's getErrors() rendering never saw the original. It now rethrows FleetbaseRequestValidationException untouched and keeps wrapping everything else, so database and internal errors still do not leak. bulkDelete() listed catch (\Exception) before its QueryException and FleetbaseRequestValidationException catches, leaving both dead behind a @codeCoverageIgnore block that acknowledged as much. The catches are now ordered most specific first and the ignore block is gone because the branches are reachable and covered. Create and single delete were already correct and are unchanged. Fixes #256
roncodes
force-pushed
the
feature/github-issue-256-review-3717b2
branch
from
September 16, 2026 04:08
d3dd3b2 to
09af864
Compare
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## release/v1.6.62 #259 +/- ##
===================================================
Coverage 100.00% 100.00%
- Complexity 6750 6751 +1
===================================================
Files 398 398
Lines 22505 22511 +6
===================================================
+ Hits 22505 22511 +6
Flags with carried forward coverage won't be shown. Click here to find out more. ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fixes #256.
An observer that refuses a write by throwing
FleetbaseRequestValidationExceptionhad its explanation discarded on two paths. The write was still refused, but the caller sawInvalid requestorError occurred while trying to update a Widgetinstead of the message the observer wrote. Both sites already had a handler for this exception; each was made unreachable by a catch block one frame deeper.What changed
HasApiModelBehavior::updateRecordFromRequest()catchesFleetbaseRequestValidationExceptionahead of its catch-all and rethrows it untouched, soHasApiControllerBehavior::updateRecord()and the global exception handler can rendergetErrors(). The catch-all keeps wrapping every other exception exactly as before, so database and internal errors still do not leak in production.HasApiControllerBehavior::bulkDelete()now catchesFleetbaseRequestValidationException, thenQueryException, then\Exception. The two specific catches were previously dead code behind the catch-all and were wrapped in a@codeCoverageIgnoreblock acknowledging that; the block is gone because the branches are now reachable and covered.RELEASE.mdgains a Fixes section for this change.Create and single-delete paths were already correct and are unchanged.
Tests
HasApiModelBehaviorTest: a model whoseupdatingevent throws the exception propagates the same instance withgetErrors()intact under bothapp.debugsettings, and the row is left unmodified.HasApiControllerBehaviorTest:updateRecord()andbulkDelete()return the observer's errors array, andbulkDelete()surfaces aQueryExceptionmessage through its now-reachable catch.Both new tests fail against the previous code and pass with the fix.
Validation
composer test:lintpasses.composer test:date-driftpasses.