fix: Emit an error when the stream closes before any response#111
Merged
Conversation
On Linux, swift-corelibs-foundation (libcurl) terminates a 3xx redirect with an empty or missing Location header by completing the task with no error and no response -- no didReceive, no willPerformHTTPRedirection callback. EventSource treated that as a normal close and reconnected forever, never emitting an error, so the SSE contract tests "client handles empty/missing Location header with 301/307 status" timed out. (CFNetwork surfaces it as an error, so macOS passed.) Treat a no-error completion that never opened the stream as an unrecoverable error and stop, giving deterministic behavior across platforms. Adds a regression test that finishes a request with no response and asserts an unrecoverable error with no reconnect.
dc078d0 to
71de077
Compare
tanderson-ld
approved these changes
Jul 16, 2026
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.
On Linux, swift-corelibs-foundation (libcurl) terminates a 3xx redirect with an
empty or missing Location header by completing the task with no error and no
response -- no didReceive, no willPerformHTTPRedirection callback. EventSource
treated that as a normal close and reconnected forever, never emitting an error,
so the SSE contract tests "client handles empty/missing Location header with
301/307 status" timed out. (CFNetwork surfaces it as an error, so macOS passed.)
Treat a no-error completion that never opened the stream as an unrecoverable
error and stop, giving deterministic behavior across platforms. Adds a
regression test that finishes a request with no response and asserts an
unrecoverable error with no reconnect.
Note
Medium Risk
Changes connection teardown in
didCompleteWithErrorfor a narrow edge case; misclassification could stop valid reconnects or still loop, but scope is limited to tasks that never reached.open.Overview
Fixes infinite reconnect when a URLSession task completes successfully but never delivers headers (so
readyStatenever becomes.open). On Linux/libcurl this happens for 3xx redirects with empty or missingLocation; macOS often reports an error instead.In
urlSession(_:task:didCompleteWithError:), a new branch treats no error + never opened as an unrecoverableEventSourceError, sets shutdown, finishes the stream, and skips the reconnect loop.Adds
closeWithoutResponseEmitsUnrecoverableErrorto finish a mock request without responding and assert a non-recoverable error with no follow-up request.Reviewed by Cursor Bugbot for commit 71de077. Bugbot is set up for automated code reviews on this repo. Configure here.