mastra-ai/mastra · error
Bad Request: No valid session ID provided for non-initialize
Error message
Bad Request: No valid session ID provided for non-initialize request
What it means
For stateful Streamable HTTP, every POST other than the initial initialize request must carry a valid session id header. If a POST arrives without one, the server responds 400 with JSON-RPC code -32000 and message 'Bad Request: No valid session ID provided for non-initialize request', because it cannot route the message to any session transport.
Source
Thrown at packages/mcp/src/server/server.ts:2210
// Also clean up the server instance for this session
if (this.httpServerInstances.has(closedSessionId)) {
this.httpServerInstances.delete(closedSessionId);
this.logger.debug('Cleaned up server instance for closed session', { sessionId: closedSessionId });
}
}
};
// Connect the new server instance to the new transport
await sessionServerInstance.connect(transport);
// Handle the initialize request. This assigns the session ID and
// triggers onsessioninitialized, which stores the transport and
// server instance for the session.
return await transport.handleRequest(req, res, body);
} else {
// POST request but not initialize, and no session ID
this.logger.warn('Received non-initialize POST request without session ID');
res.writeHead(400, { 'Content-Type': 'application/json' });
res.end(
JSON.stringify({
jsonrpc: '2.0',
error: {
code: -32000,
message: 'Bad Request: No valid session ID provided for non-initialize request',
},
id: (body as any)?.id ?? null, // Include original request ID if available
}),
);
}
} else {
// Non-POST request (GET/DELETE) without a session ID
this.logger.warn('Received request without session ID', { method: req.method });
res.writeHead(400, { 'Content-Type': 'application/json' });
res.end(
JSON.stringify({
jsonrpc: '2.0',View on GitHub (pinned to 75dd419e61)
Solutions
- Send an initialize request first and echo the returned mcp-session-id header on every subsequent request
- Use the official MCP SDK client transport, which manages the session id automatically
- Check that proxies/middleware/CORS exposed headers preserve the mcp-session-id header
- If you don't need sessions, run the server in stateless mode (serverless: true or sessionIdGenerator: undefined) where this requirement doesn't apply
Example fix
// before
await fetch('http://localhost:4111/mcp', { method: 'POST', body: rpc }); // no session header
// after
const init = await fetch(url, { method: 'POST', headers: jsonHeaders, body: initRpc });
const sessionId = init.headers.get('mcp-session-id');
await fetch(url, { method: 'POST', headers: { ...jsonHeaders, 'mcp-session-id': sessionId }, body: rpc }); Defensive patterns
Strategy: validation
Validate before calling
function requireSessionHeader(headers, isInitialize) {
if (!isInitialize && !headers['mcp-session-id']) {
throw new Error('Non-initialize MCP requests must include the mcp-session-id header');
}
} Try / catch
if (res.status === 400) {
const body = await res.json();
if (body?.error?.code === -32000 && String(body.error.message).includes('session ID')) {
// re-run initialize, capture mcp-session-id, then retry the request
}
} Prevention
- Always perform initialize first and propagate the returned mcp-session-id to every request
- Prefer the official MCP SDK client transport over hand-rolled fetch calls
- Ensure CORS exposedHeaders and proxy configs preserve the mcp-session-id header
- Use stateless/serverless mode on the server if clients cannot maintain sessions
When it happens
Trigger: POSTing tools/call, notifications, or any non-initialize JSON-RPC message without the mcp-session-id header; using a hand-rolled HTTP client that never stores and replays the session id returned at initialize; proxy/gateway stripping the session header.
Common situations: Custom MCP clients built with fetch instead of the SDK; header-filtering middleware or CORS configurations dropping mcp-session-id; calling the endpoint directly (curl/Postman) after copying only an initialize example; stateless serverless callers hitting a stateful server.
Related errors
- Bad Request: ${req.method} request requires a valid session
- JSON.stringify(errorResponse)
- Could not connect to server with any available HTTP transpor
- MCPClientServerProxy does not support HTTP transport
- MCP_SERVER_MODERN_HTTP_OPTIONS_INCOMPATIBLE
AI-assisted analysis of mastra-ai/mastra@75dd419e61 (2026-08-30).
Data as JSON: /api/errors/00d8decb586516f2.
Report an issue: GitHub.