You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
HttpServletStreamableServerTransportProvider intermittently answers -32603 "Stream unavailable for session <id>" (wrapped as JSON-RPC internal error / HTTP 500) when it attempts to push a server-initiated request (e.g. roots/list) to a client whose GET /mcp SSE stream has not been registered yet.
Unable to reproduce locally, even running the tests 1000 times. It might not be the exact problem described here. The test in question does the following:
client initializes fully
POST /initialize`
GET /mcp (opens a stream), in a fire-and-forget
POST notifications/initialized
client notify roots lists changes POST notications/roots/list_changed
Only when the server gets the notification does the server sends roots/list.
It is very unlikely that the GET is under contention for two full posts. I can reproduce by adding latency to the servlet transport's doGet, though.
The underlying issue (race condition between server notifications and GET) might be a problem under some conditions (network, client from a different ecosystem).
(There is also a separate issue at play here - the client can't really wait for the stream to be established before proceeding further, which would fix the test without fixing the race condition. But that's a whole other can of worms.)
Fresh occurrence in CI, on a branch that only touches a test file: Jackson 2 job of #1113 at 8fccf33, HttpServletStreamableIntegrationTests.testRootsSuccess(String)[1] → -32603 "Error processing message: Stream unavailable for session f79d57db-…" from HttpServletStreamableServerTransportProvider.doPost:564 (run 33192309921). Same seam as testRootsNotificationWithEmptyRootsList; the sibling Jackson 3 job passed the same class.
I can help investigate this race. The current discussion suggests the server-side contract needs to distinguish a session that exists from a stream that is not registered yet. Before proposing code, would maintainers prefer buffering pending server-to-client messages per session (with bounded lifetime) or a retryable send result? I can prepare a deterministic delayed-GET integration test once the preferred invariant is confirmed.
Looking around at what the other SDKs do, CSharp, TypeScript and Python suffer the same race condition and don't try to buffer or replay. I don't plan on changing the current behavior, especially with the new spec around the corner that has most of our focus.
I'm open to stabilizing the tests though.
The issue is with server-sent notifications, so possibly roots, elicitiation and sampling. They seem to mostly be happening in roots, so I'll add the explicit await there.
Fine with stabilizing the tests and leaving the server behavior as-is, given parity with the C#/TS/Python SDKs and the upcoming spec revision. Since #1119 does not change the runtime race, I would suggest closing this as not-planned rather than via "Fixes", so the decision stays discoverable when the 2026-07-28 transport work touches this seam.
Activity
Kehrlann commentedon Aug 28, 2026
Unable to reproduce locally, even running the tests 1000 times. It might not be the exact problem described here. The test in question does the following:
POST/initialize`GET /mcp(opens a stream), in a fire-and-forgetPOST notifications/initializedPOST notications/roots/list_changedroots/list.It is very unlikely that the
GETis under contention for two full posts. I can reproduce by adding latency to the servlet transport'sdoGet, though.The underlying issue (race condition between server notifications and
GET) might be a problem under some conditions (network, client from a different ecosystem).(There is also a separate issue at play here - the
clientcan't really wait for the stream to be established before proceeding further, which would fix the test without fixing the race condition. But that's a whole other can of worms.)Kehrlann commentedon Aug 28, 2026
Please let's discuss server-side fixes in this issue before jumping into an implementation.
slachiewicz commentedon Aug 28, 2026
Fresh occurrence in CI, on a branch that only touches a test file: Jackson 2 job of #1113 at 8fccf33,
HttpServletStreamableIntegrationTests.testRootsSuccess(String)[1]→-32603 "Error processing message: Stream unavailable for session f79d57db-…"fromHttpServletStreamableServerTransportProvider.doPost:564(run 33192309921). Same seam astestRootsNotificationWithEmptyRootsList; the sibling Jackson 3 job passed the same class.This comment was created with AI assistance.
CryoThrust commentedon Aug 31, 2026
I can help investigate this race. The current discussion suggests the server-side contract needs to distinguish a session that exists from a stream that is not registered yet. Before proposing code, would maintainers prefer buffering pending server-to-client messages per session (with bounded lifetime) or a retryable send result? I can prepare a deterministic delayed-GET integration test once the preferred invariant is confirmed.
Kehrlann commentedon Aug 31, 2026
Looking around at what the other SDKs do, CSharp, TypeScript and Python suffer the same race condition and don't try to buffer or replay. I don't plan on changing the current behavior, especially with the new spec around the corner that has most of our focus.
I'm open to stabilizing the tests though.
The issue is with server-sent notifications, so possibly
roots,elicitiationandsampling. They seem to mostly be happening inroots, so I'll add the explicit await there.slachiewicz commentedon Aug 31, 2026
Fine with stabilizing the tests and leaving the server behavior as-is, given parity with the C#/TS/Python SDKs and the upcoming spec revision. Since #1119 does not change the runtime race, I would suggest closing this as not-planned rather than via "Fixes", so the decision stays discoverable when the 2026-07-28 transport work touches this seam.
This comment was created with AI assistance.
Fix integration tests for `roots/list`
Fix integration tests for `roots/list`
Fix integration tests for `roots/list`