Skip to content

Handle response for closed MVC WebSocket session - #1503

Merged
bclozel merged 1 commit into
spring-projects:2.0.xfrom
Meemaw:gh-1501-handle-closed-session-in-response
Aug 10, 2026
Merged

Handle response for closed MVC WebSocket session#1503
bclozel merged 1 commit into
spring-projects:2.0.xfrom
Meemaw:gh-1501-handle-closed-session-in-response

Conversation

@Meemaw

@Meemaw Meemaw commented Aug 10, 2026

Copy link
Copy Markdown

Closes gh-1501

Follow-up to gh-1449 / #1451, which guarded the inbound message path against a session whose state has already been removed during connection close. The same race exists on the response path: if the session is closed while a subscribe request is still executing, the doOnSubscribe callback in handleResponse fails with IllegalArgumentException: No SessionInfo for ..., which is then logged at ERROR level as Unresolved IllegalArgumentException for request id <id>, and an error message send is attempted on the already-closed session.

This change looks up the session state non-assertively in handleResponse and, when the session state is already gone, cancels the response publisher instead of throwing. Cancellation (rather than an error or empty completion) is deliberate: the per-session send scheduler is disposed in afterConnectionClosed, so any terminal signal flowing through the publishOn would fail with RejectedExecutionException: Scheduler unavailable.

The responseAfterConnectionClosed test holds the response back with an interceptor until after afterConnectionClosed, and asserts the late response is silently dropped. It fails without the fix and passes with it.

On a high-traffic production subscription endpoint this signature accounts for roughly 44,000 ERROR logs per 7 days, proportional to normal client disconnect churn.

@bclozel

bclozel commented Aug 10, 2026

Copy link
Copy Markdown
Member

@Meemaw please sign the DCO, we cannot accept this contribution without it.

@bclozel bclozel self-assigned this Aug 10, 2026
@Meemaw
Meemaw force-pushed the gh-1501-handle-closed-session-in-response branch from c423e5a to f7e320f Compare August 10, 2026 16:33
@Meemaw

Meemaw commented Aug 10, 2026

Copy link
Copy Markdown
Author

@bclozel done!

Prior to this commit, if a WebSocket session was closed while a
subscription request was still executing, response handling would fail
to register the subscription with "No SessionInfo" from the doOnSubscribe
callback, log the IllegalArgumentException at ERROR level as unresolved,
and attempt to send an error message to the already-closed session.

This commit ignores responses received after the WebSocket session state
has already been removed during connection close, cancelling the response
publisher instead, consistent with the inbound message handling added
in spring-projectsgh-1449.

Closes spring-projectsgh-1501

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Signed-off-by: Meemaw <ematej.snuderl@gmail.com>
@bclozel
bclozel changed the base branch from main to 2.0.x August 10, 2026 16:49
@bclozel
bclozel force-pushed the gh-1501-handle-closed-session-in-response branch from f7e320f to d672496 Compare August 10, 2026 16:49
@bclozel
bclozel merged commit d672496 into spring-projects:2.0.x Aug 10, 2026
1 check failed
@bclozel bclozel added type: enhancement A general enhancement in: web Issues related to web handling and removed status: waiting-for-triage An issue we've not yet triaged labels Aug 10, 2026
@bclozel bclozel added this to the 2.0.5 milestone Aug 10, 2026
@bclozel

bclozel commented Aug 10, 2026

Copy link
Copy Markdown
Member

Thanks for your contribution @Meemaw, this will be released in the next 2.0.x maintenance version in a few days.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

in: web Issues related to web handling type: enhancement A general enhancement

Projects

None yet

Development

Successfully merging this pull request may close these issues.

GraphQlWebSocketHandler response handling still fails with "No SessionInfo" when the session is closed concurrently (WebMVC)

3 participants