gate-49 accepts a catch only for one of nine named domain exceptions:
TRACKED = [DoesNotExistException, MultipleObjectsReturnedException, NotFoundException,
PermissionException, ValidationException, ForbiddenException,
CustomValidationException, AppendOnlyException, ArchivalImmutableException]
catch (\Throwable $e) matches none of them — yet it catches all nine, plus everything else. So the broadest possible translation is reported as no translation at all.
Hit on ConductionNL/hermiq#162: SettingsController::index/create/load were flagged with no handling, I added catch (\Throwable) to each with a translated JSON response and a log, and the gate still reports "3 controller method(s) missing try/catch or @throws".
Why it matters beyond a false positive
The finding pushes authors toward the narrower fix. Catching only DoesNotExistException where the real risk is "the service blew up for a reason I have not enumerated" leaves the uncaught path — a framework 500 with a stack trace — exactly where it was. For index() that trace reaches a non-admin, since the method is #[NoAdminRequired].
Suggested
Treat catch (\Throwable) and catch (\Exception) as satisfying the gate. They are supersets of the tracked list; a gate that rejects the stronger guarantee teaches people to write the weaker one.
Worked around for now with the documented opt-out ([hydra-gate-controller-exception-translation exclude] …), which is the right escape hatch but should not be needed for the broadest correct handler.
Related: #203 — gate-55 and gate-60 encode two different icon registries for the same widget field, with no opt-out at all.
gate-49 accepts a
catchonly for one of nine named domain exceptions:catch (\Throwable $e)matches none of them — yet it catches all nine, plus everything else. So the broadest possible translation is reported as no translation at all.Hit on ConductionNL/hermiq#162:
SettingsController::index/create/loadwere flagged with no handling, I addedcatch (\Throwable)to each with a translated JSON response and a log, and the gate still reports "3 controller method(s) missing try/catch or @throws".Why it matters beyond a false positive
The finding pushes authors toward the narrower fix. Catching only
DoesNotExistExceptionwhere the real risk is "the service blew up for a reason I have not enumerated" leaves the uncaught path — a framework 500 with a stack trace — exactly where it was. Forindex()that trace reaches a non-admin, since the method is#[NoAdminRequired].Suggested
Treat
catch (\Throwable)andcatch (\Exception)as satisfying the gate. They are supersets of the tracked list; a gate that rejects the stronger guarantee teaches people to write the weaker one.Worked around for now with the documented opt-out (
[hydra-gate-controller-exception-translation exclude] …), which is the right escape hatch but should not be needed for the broadest correct handler.Related: #203 — gate-55 and gate-60 encode two different icon registries for the same widget field, with no opt-out at all.