{
  "schema_version": "1.3.0",
  "slug": "under-what-conditions-must-an-instance-treat-an-mcp-session-resumption-token-as-invalid-despite-a-syntactically-valid-http-request",
  "title": "Under what conditions must an instance treat an MCP session resumption token as invalid despite a syntactically valid HTTP request",
  "date_of_record": "2026 November 7",
  "scope": "Applies to MCP servers exposing the HTTP-native streamable transport with SSE fallback and `Last-Event-ID`-based resumption, where session identity is carried via an `Mcp-Session-Id` header and the resumption cursor is an opaque server-issued event ID. Does not apply to stdio transports, to stateless streamable endpoints that never issue session IDs, or to clients that reconnect by replaying the entire request body rather than resuming a stream.",
  "projections": {
    "unified_markdown_uri": "https://corpusfetch.com/c/under-what-conditions-must-an-instance-treat-an-mcp-session-resumption-token-as-invalid-despite-a-syntactically-valid-http-request.md",
    "method_python_slice_uri": "https://corpusfetch.com/c/under-what-conditions-must-an-instance-treat-an-mcp-session-resumption-token-as-invalid-despite-a-syntactically-valid-http-request.py",
    "remnant_warrant_slice_uri": "https://corpusfetch.com/c/under-what-conditions-must-an-instance-treat-an-mcp-session-resumption-token-as-invalid-despite-a-syntactically-valid-http-request.warrant.json"
  },
  "token_profile": {
    "full_markdown_tokens": 1667,
    "python_slice_tokens": 265,
    "warrant_slice_tokens": 220
  },
  "remnant_summary": {
    "core_distinction": "The distinction that matters is between **transport-level validity** and **session-level validity**. A resumption request can be a perfectly well-formed HTTP request — correct method, correct `Accept: text/event-stream`, syntactically valid `Mcp-Session-Id`, syntactically valid `Last-Event-ID` — and still be *semantically unresumable*. The transport layer on...",
    "what_was_observed": "During failover testing of a streamable MCP server behind a load balancer, the following sequence reproduced reliably: 1. Client opens a stream, receives `Mcp-Session-Id: S1` and events with IDs `e1..e100`. 2. Client disconnects at `e100` to simulate a network partition. 3. The backend instance holding session `S1` is drained and replaced. The new instance has no memory of `S1`. 4. Client reconnects with `Mcp-Session...",
    "condition_of_validity": "A resumption token `(S, E)` — session `S`, event cursor `E` — is valid **only if all three of the following hold simultaneously**: 1. **Session liveness:** `S` exists in the session registry and has not exceeded its idle TTL or absolute TTL. 2. **Cursor provenance:** `E` was issued by the event stream bound to `S`. A cursor from session `S'` presented agains...",
    "decision_boundary": "The server must choose, per resumption request, among four responses, and the boundary between them is not the HTTP status: - **Resume:** all three conditions hold → `200`, stream from `E`. - **Gap:** (1) and (2) hold, (3) fails → `200` with a structured `gap` signal in the first event, or `409` with a body naming the earliest replayable cursor. Never silent...",
    "operational_effect": "The practical consequence is that **session resumption cannot be validated at the transport layer alone**. Any proxy, gateway, or load balancer that terminates TLS and forwards based on header syntax will happily pass a resumption request for a session it cannot see. The server — the only component with access to the session registry and the replay buffer — ..."
  },
  "matched_failure_symptoms": [
    "DOMAIN:EPISTEMIC_PROVENANCE_AND_FEDERATION_ROUTING"
  ],
  "composition_edges": {
    "primary_domain": "epistemic_provenance_and_federation_routing",
    "upstream_precondition_residuals": [
      "https://corpusfetch.com/c/according-to-what-precedence-hierarchy-must-an-instance-resolve-contradictory-directives-across-system-developer-and-user-tiers.md",
      "https://corpusfetch.com/c/how-should-an-instance-decide-that-a-stored-conclusion-has-gone-stale-without-a-new-observation.md"
    ],
    "downstream_consequence_residuals": [
      "https://corpusfetch.com/c/by-what-checkpoint-and-compaction-boundaries-must-an-instance-externalize-working-state-to-prevent-context-window-drift-and-truncation-amnesia.md",
      "https://corpusfetch.com/c/across-what-additive-schema-and-unknown-field-preservation-boundaries-must-an-instance-evolve-wire-contracts-to-prevent-rolling-deploy-deserialization-crashes.md"
    ],
    "co_occurring_sibling_residuals": [
      "https://corpusfetch.com/c/how-can-an-instance-capture-implicit-user-preferences-without-storing-private-data.md",
      "https://corpusfetch.com/c/how-can-an-instance-compress-long-reasoning-traces-into-binding-conclusions.md"
    ]
  },
  "empirical_verification_warrant": {
    "status": "AST_AND_INVARIANT_VERIFIED",
    "syntax_valid": true,
    "code_sha256": "c37a8bc7acd99a0f932dcd7899fff383ff39bf7f63175f10a167b6260901dc39",
    "verified_classes": [
      "ResumptionTokenError",
      "CursorProvenanceError",
      "SessionUnknownError",
      "ReplayGapError",
      "SessionRecord"
    ],
    "verified_functions": [
      "validate_resumption"
    ],
    "verified_functions_count": 1,
    "defensive_guards_count": 4,
    "raised_exceptions": [
      "CursorProvenanceError",
      "ReplayGapError",
      "ResumptionTokenError",
      "SessionUnknownError"
    ],
    "sample_fail_closed_invariants": [],
    "stdlib_dependencies": [
      "dataclasses",
      "typing"
    ],
    "observation_mode": "EMPIRICAL_BOUNDARY_CAPTURE",
    "zero_external_deps": true
  }
}
