different-ai/openwork · warning
MCP_SESSION_NOT_FOUND
MCP_SESSION_NOT_FOUND
Error message
MCP_SESSION_NOT_FOUND
What it means
MCP_SESSION_NOT_FOUND is produced when an MCP request returns HTTP 404 while the gateway knows a session had been established (input.hasSession). The classifier treats this as a CONTINUITY_SESSION / mcp_session_expired problem: the session id the client is presenting is no longer recognized by the server. Unlike a plain endpoint 404, it is retryable because reinitializing the session should restore operation.
Source
Thrown at ee/apps/den-api/src/capability-sources/external-mcp-diagnostics.ts:899
...(input.providerRequestId ? { providerRequestId: input.providerRequestId } : {}),
})
}
function httpClassification(input: {
phase: ExternalMcpDiagnosticPhase
status: number
hasAuthorization: boolean
bearerChallenge: boolean
insufficientScope: boolean
hasSession: boolean
contentType: string
}): Classification | null {
const { phase, status } = input
if (status === 404 && input.hasSession) {
return {
phase: "CONTINUITY_SESSION",
category: "mcp_session_expired",
code: "MCP_SESSION_NOT_FOUND",
retryable: true,
actionOwner: "openwork",
operatorAction: "Reinitialize the MCP session, then retry the operation once.",
}
}
if (status === 404 && phase.startsWith("MCP_")) {
return {
phase: "HTTP_ROUTING",
category: "endpoint_not_found",
code: "MCP_HTTP_404",
retryable: false,
actionOwner: "organization_admin",
operatorAction: "Verify the complete MCP endpoint path, including any provider tenant or instance prefix.",
}
}
if ((status === 406 || status === 415) && phase.startsWith("MCP_")) {
return {
phase: "MCP_TRANSPORT",View on GitHub (pinned to 2b7df46e8a)
Solutions
- Reinitialize the MCP session (new initialize handshake to obtain a fresh Mcp-Session-Id).
- Retry the failed operation once with the new session, as the diagnostic prescribes.
- If it recurs, shorten the interval between calls or enable session keep-alive; verify the load balancer is not splitting session traffic.
Example fix
// before: reusing a stale session id
const res = await fetch(mcpUrl, { headers: { 'Mcp-Session-Id': staleId, ... } })
// after: reinitialize and reuse the new session id
const init = await initialize(mcpUrl)
const res = await fetch(mcpUrl, { headers: { 'Mcp-Session-Id': init.sessionId, ... } }) Defensive patterns
Strategy: retry
Validate before calling
// check session freshness before reuse
async function sessionValid(url: string, sessionId: string): Promise<boolean> {
const res = await fetch(url, { method: 'GET', headers: { 'Mcp-Session-Id': sessionId } })
return res.status !== 404
} Type guard
function isSessionExpired(d: { code: string; category?: string }): boolean {
return d.code === 'MCP_SESSION_NOT_FOUND' || d.category === 'mcp_session_expired'
} Try / catch
try {
return await withSession(sessionId, () => client.callTool(req))
} catch (e) {
if (isSessionExpired(e.diagnostic)) {
const fresh = await initialize(mcpUrl) // one reinitialize + single retry
return await withSession(fresh.sessionId, () => client.callTool(req))
}
throw e
} Prevention
- Send periodic keep-alive/ping requests to keep long-lived MCP sessions from expiring.
- Reinitialize the session after any server restart or redeploy of the provider.
- Avoid caching Mcp-Session-Id across processes or longer than the provider's session TTL.
When it happens
Trigger: Any request sent during an MCP phase (e.g. MCP_TOOL_EXECUTION or MCP_TOOL_DISCOVERY) with a previously negotiated Mcp-Session-Id header where the server responds 404, and hasSession is true. Typical call: client.callTool(...) on a streamable-HTTP MCP connection after the server dropped the session.
Common situations: Server restart or redeploy between calls invalidating in-memory sessions; server-side session TTL/timeout expiring during long pauses; load balancer routing to a replica without the session state; provider upgraded and rotated session stores.
Related errors
AI-assisted analysis of different-ai/openwork@2b7df46e8a (2026-09-01).
Data as JSON: /api/errors/71c48f7618505bb2.
Report an issue: GitHub.