Repository navigation
fix(errors-advanced): report warnings as non-fatal instead of rendering a page - #682
Open
etienne-scherrer wants to merge 1 commit into
Open
etienne-scherrer wants to merge 1 commit into
etienne-scherrer wants to merge 1 commit into
Conversation
etienne-scherrer
marked this pull request as ready for review
November 3, 2026 22:42
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.
Problem
With
errors-advanced, a PHP warning renders a full error page, and then the code that warned keeps running.AdvancedErrorHandler::handleError()sendsE_WARNINGdown the fatal path:handleException()clears the output buffers, sets status 500 andContent-Type: text/html, echoes the page, andhandleError()returnstrue, so PHP resumes.When the controller's response is sent afterwards,
Response::sendHeaders()skips every header because headers are already out, butResponse::send()still writes the body. The response's own status,Content-Type, security headers,Locationand cookies are lost, and its body is appended to the HTML error page, so a JSON or plain text body that reflects request input is then served as HTML. In PHP 8 a missing array key is a warning, so a request can trigger this on purpose.A controller that checks a warning-prone call and redirects shows it:
The visitor gets a 500 page, the redirect's
Locationand cookies (the session cookie included) are silently dropped, and the controller ran to the end anyway.errors-simpledoes not have this problem: since b6bd408 it treatsSeverity::Warningas non-fatal and reports it througherror_login the web SAPI, aserrors-simple.mddocuments.Change
AdvancedErrorHandler::handleError()treatsSeverity::Warningas non-fatal, likeSimpleErrorHandler.handleNonFatal()writes[Warning] message in file:linetoerror_login the web SAPI instead of returning silently, through awriteToErrorLog()hook as in errors-simple. The CLI keeps writing toSTDERR.errors-advanced.mdstates the non-fatal policy, matchingerrors-simple.md.Warnings stay loud, in the log instead of the response. Fatal errors and uncaught exceptions still render the page.
Tests
error_logwith no output, no status and no headers (failed before: the page was rendered).E_USER_WARNINGas non-fatal.Each of the three fails when warnings are made fatal again.
pest --parallelinphp:8.5-cliwith the suite's extensions: 14173 passed, 449 skipped, 15 failed; the 15 (GdImageProcessorTest,GdImageProcessorLimitsTest,IntegrationVerificationTest,RepoManagementScriptsTest) fail the same way on a cleandevelopin that container.phpcs,php-cs-fixer --dry-run,docs:lintandphpstan: clean.Not in this PR:
Response::json()could addJSON_HEX_TAG | JSON_HEX_AMP, so a JSON body can never be read as markup even if headers are lost some other way. Happy to send that separately.