Fix TypeError in Http::retry() when callback receives null (fixes laravel/framework#59012)#6
Closed
JoshSalway wants to merge 2 commits into12.xfrom
Closed
Fix TypeError in Http::retry() when callback receives null (fixes laravel/framework#59012)#6JoshSalway wants to merge 2 commits into12.xfrom
JoshSalway wants to merge 2 commits into12.xfrom
Conversation
…xception Verifies that Http::retry() does not throw TypeError when the when callback type-hints Exception or Throwable and the response is a 3xx status code (where toException() returns null). Refs laravel#59012 Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
When Http::retry() receives a non-failed response (e.g. 3xx), toException() returns null. Passing null to a when callback that type-hints Exception or Throwable causes a TypeError. Skip calling the when callback when there is no exception to pass, defaulting to the same behavior as having no when callback. Fixes laravel#59012 Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
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.
Summary
Fixes laravel#59012 --
Http::retry()throws aTypeErrorwhen the retry callback has a typedExceptionorThrowableparameter and the response has a non-error status code (like 302). ThetoException()method returnsnullfor non-error responses, but the callback receivesnullwhere it expects an exception object.Root Cause
The bug exists because
Response::toException()returnsnullwhen the response status is not a client/server error (4xx/5xx). The retry logic callscall_user_func($this->retryWhenCallback, $response->toException(), ...)unconditionally, passingnullas the first argument. When the callback has a type-hinted parameter likefn (Exception $e) => ..., PHP throws aTypeErrorbecausenullis not anException.This affects any retry configuration where the server returns redirects (302), informational (1xx), or other non-error responses. The retry callback fires on every response, not just errors.
Why This Fix Works
This fix works because it extracts
$response->toException()into a variable and adds a null check:$this->retryWhenCallback && $exception ? call_user_func(...) : true. When the exception isnull(meaning the response is not an error), the retry logic defaults totrue(don't retry -- the request succeeded). This prevents the null value from ever reaching the typed callback parameter. The same fix is applied to both synchronoussend()and asynchronoushandlePromiseResponse()code paths.Alternatives Considered
We chose this approach over wrapping the callback in a try-catch for
TypeErrorbecause: (1) silencing a TypeError would mask legitimate bugs in user callbacks; (2) the semantic intent is clear -- a non-error response should not trigger retry logic at all; (3) defaulting totrue(don't retry) for non-error responses matches the expected behavior -- you only retry failures.Files Changed
src/Illuminate/Http/Client/PendingRequest.php-- Null-guard ontoException()result in both sync and async retry pathstests/Http/HttpClientTest.php-- 2 new tests for typed Exception and Throwable callback parameters with non-error responses