12D: Never let a hook throw, whatever the host's code does - #25
Open
nikolaystrikhar wants to merge 1 commit into
Open
12D: Never let a hook throw, whatever the host's code does#25nikolaystrikhar wants to merge 1 commit into
nikolaystrikhar wants to merge 1 commit into
Conversation
Configuration still throws -- register() rejects a bad config array where the host can see its own call in the stack trace. Everything the library puts on a hook now catches Throwable, reports it with _doing_it_wrong() and abandons that step: the plugins_loaded step in Boot\Scheduler, and render_notices() on all_admin_notices. The load pass catches per sub-plugin as well. Past that catch is somebody else's code -- the enabled and dependency_check callables, the conflict policy and its filter, the notice messages, should_load, and the bundled file a require runs top to bottom -- and a throw from one sub-plugin took the whole site down, front end included, along with every sub-plugin behind it in the registration order. The step reporter takes the step's name and what the site got instead, because the sequence gains a second step at the priority ahead of this one and both have to report the same way. A re-declaration is the one failure none of this catches, because PHP does not raise it as a Throwable. The guard constant, checked before the require, is what has always prevented that one.
nikolaystrikhar
force-pushed
the
12C-registry-reader
branch
from
August 13, 2026 11:01
2b5ea5c to
21db929
Compare
nikolaystrikhar
force-pushed
the
12D-hook-guard
branch
from
August 13, 2026 11:01
e7d7a7a to
f3e63d9
Compare
d4mation
approved these changes
Aug 13, 2026
d4mation
left a comment
There was a problem hiding this comment.
This is nice! Especially if something like the enabled callback references something that suddenly stops existing this could be a big deal.
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.
What: the
plugins_loadedstep inBoot\Scheduler,Absorber::render_notices()onall_admin_notices, andLoader::load_all()per sub-plugin all catchThrowable, report with_doing_it_wrong()and abandon that step alone.Usage:
Why this way:
Configuration still throws.
register()rejects a bad config array on the spot, at a call in the developer's own stack trace, before anything is hooked. Past that point this library is code on somebody's live site, and a white screen is never the better answer.The load pass catches per sub-plugin as well. Everything past that catch is host code — the
enabledanddependency_checkcallables, the notice messages,should_load, and the bundled file arequireruns top to bottom — and one sub-plugin's throw took the whole site down, front end included, along with every sub-plugin behind it in the registration order.The reporter takes the step's name and what the site got instead, because the sequence gains a second step at the priority ahead of this one and both have to report the same way.
A re-declaration is the one failure none of this catches, since PHP does not raise it as a
Throwable. The guard constant, checked before the require, is what has always prevented that one.