Skip to content

fix: return 404 for unknown session IDs so clients re-initialize - #20

Merged
ConalMullan merged 1 commit into
developfrom
fix/expired-session-404
Aug 12, 2026
Merged

fix: return 404 for unknown session IDs so clients re-initialize#20
ConalMullan merged 1 commit into
developfrom
fix/expired-session-404

Conversation

@ConalMullan

Copy link
Copy Markdown
Collaborator

Problem

The MCP Streamable HTTP spec requires 404 for a request carrying an unknown or expired Mcp-Session-Id — it is the client's cue to start a new session with a fresh InitializeRequest. We returned 400, which clients treat as a hard error, so they stay wedged until a human reconnects them.

Hit immediately after the dev deploy of #19: the container restarted, and the connected claude.ai client could not recover on its own.

Why it matters more now

#19 added idle session sweeping. Every session idle past SESSION_IDLE_TIMEOUT_MS now hits this path — so without the correct status code, the sweep would strand clients rather than let them reconnect transparently. The two changes need to ship together.

Change

Case Before After
POST, unknown/expired session id 400 404
GET, unknown/expired session id 400 404
DELETE, unknown/expired session id 400 404
POST, no session id, non-initialize 400 400 (unchanged)
GET/DELETE, no session id 400 400 (unchanged)

A missing session ID still returns 400 — no re-initialize cue applies there.

Verification

Against a locally built server:

POST unknown session -> HTTP 404  {"code":-32001,"message":"Session not found..."}
POST no session, non-init -> HTTP 400
GET  unknown session -> HTTP 404
GET  no session -> HTTP 400

Also confirmed on the same build that a normal session still initializes and serves tools/list (144 tools), that idle sessions are swept (activeSessions 3 → 0, sweptSessions: 3), and that a session receiving traffic every 2s survives well past a 5s idle timeout.

540 tests passing, lint and format clean.

The MCP Streamable HTTP spec requires 404 for a request carrying an
unknown or expired Mcp-Session-Id: it is the client's cue to start a new
session with a fresh InitializeRequest. We returned 400, which clients
treat as a hard error, leaving them wedged until a human reconnects.

Hit this immediately after the dev deploy: the container restarted, and
the connected claude.ai client could not recover on its own.

It matters more now that idle sessions are swept - every session idle
past SESSION_IDLE_TIMEOUT_MS hits this path, so without the correct
status code the sweep would strand clients rather than let them
reconnect transparently.

A missing (rather than unknown) session ID still returns 400, since no
re-initialize cue applies.

Verified against a locally built server:
  POST unknown session -> 404    POST no session, non-init -> 400
  GET  unknown session -> 404    GET  no session           -> 400
@ConalMullan
ConalMullan merged commit e91b394 into develop Aug 12, 2026
3 checks passed
@ConalMullan
ConalMullan deleted the fix/expired-session-404 branch August 12, 2026 07:45
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