Skip to content

upstream: re-initialize when the server expired our session (404) - #20

Merged
selic merged 1 commit into
mainfrom
fix/upstream-stale-session
Jul 25, 2026
Merged

upstream: re-initialize when the server expired our session (404)#20
selic merged 1 commit into
mainfrom
fix/upstream-stale-session

Conversation

@selic

@selic selic commented Jul 25, 2026

Copy link
Copy Markdown
Member

Summary

Production bug hit via the claude.ai connector: a publora tool call returned Upstream "publora" call failed: … {"error":"Unknown or expired MCP session. Re-initialize…"} and kept failing on every retry from the client side.

Root cause: UpstreamConnection.callTool's retry-once path only covered locally dropped transports (if (this.connected) throw err). When the upstream expires the streamable-HTTP session server-side (restart, TTL), the local SDK client still looks connected, the server answers 404, and the gateway propagated the error to the caller — who has no way to fix it, since only the gateway owns the upstream session.

Per the MCP spec, a 404 on an existing session means "re-initialize". The connection now:

  • detects it (StreamableHTTPError with code 404, plus an "unknown or expired MCP session / session not found" message fallback for untyped rethrows),
  • drops the pooled client via a deliberate reset (no backoff-reconnect churn),
  • reconnects (fresh initialize → new session) and retries the call exactly once.

Genuine tool errors still pass through untouched — no needless session churn.

Test plan

  • New integration test (connection.test.ts): real StreamableHTTPServerTransport backend; clearing its session store mid-test reproduces the 404; the next callTool transparently re-initializes (assert a second initialize arrived) and succeeds; unknown-tool errors don't trigger re-init
  • npm test — 214 passed, npm run build clean

🤖 Generated with Claude Code

The retry-once path only covered locally dropped transports. When an
upstream expires or forgets the streamable-HTTP session server-side
(restart, TTL — hit in production with Publora), the SDK client still
looks connected, the server answers 404 "Unknown or expired MCP
session", and the gateway propagated that error to the caller.

Per the MCP spec a 404 on an existing session means re-initialize: the
connection now detects it (StreamableHTTPError code 404, plus a
message fallback for untyped rethrows), drops the pooled client
without triggering backoff, reconnects and retries the call exactly
once. Genuine tool errors still pass through untouched.

Integration test runs a real StreamableHTTPServerTransport backend
whose session store is cleared mid-test to reproduce the failure.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@selic
selic merged commit 207a29d into main Jul 25, 2026
@selic
selic deleted the fix/upstream-stale-session branch July 25, 2026 10:32
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant