{"record":{"id":"26512165e30fb2a8","repo":"linshenkx/prompt-optimizer","slug":"invalid-or-missing-session-id","errorCode":null,"errorMessage":"Invalid or missing session ID","messagePattern":"Invalid or missing session ID","errorType":"http","errorClass":null,"httpStatus":400,"severity":"error","filePath":"packages/mcp-server/src/index.ts","lineNumber":443,"sourceCode":"            jsonrpc: '2.0',\n            error: {\n              code: -32000,\n              message: 'Bad Request: No valid session ID provided',\n            },\n            id: null,\n          });\n          return;\n        }\n\n        // 处理请求\n        await httpTransport.handleRequest(req, res, req.body);\n      });\n\n      // 处理 GET 请求（服务器到客户端通知，通过 SSE）\n      app.get('/mcp', async (req, res) => {\n        const sessionId = req.headers['mcp-session-id'] as string | undefined;\n        if (!sessionId || !transports[sessionId]) {\n          res.status(400).send('Invalid or missing session ID');\n          return;\n        }\n\n        const httpTransport = transports[sessionId];\n        await httpTransport.handleRequest(req, res);\n      });\n\n      // 处理 DELETE 请求（会话终止）\n      app.delete('/mcp', async (req, res) => {\n        const sessionId = req.headers['mcp-session-id'] as string | undefined;\n        if (!sessionId || !transports[sessionId]) {\n          res.status(400).send('Invalid or missing session ID');\n          return;\n        }\n\n        const httpTransport = transports[sessionId];\n        await httpTransport.handleRequest(req, res);\n      });","sourceCodeStart":425,"sourceCodeEnd":461,"githubUrl":"https://github.com/linshenkx/prompt-optimizer/blob/3e677b1d9f7e0493c142c175560531e7ae786dce/packages/mcp-server/src/index.ts#L425-L461","documentation":"The GET /mcp endpoint (server-to-client SSE notifications) requires an mcp-session-id header matching a transport in the in-memory transports map. A missing header or an unknown/expired session ID yields HTTP 400 with this plain-text body.","triggerScenarios":"GET /mcp with no mcp-session-id header, with a session ID from before a server restart, or after the session was deleted via DELETE /mcp; long-lived SSE clients that never re-initialize.","commonSituations":"Server process restarted (transports map is memory-only and empty), horizontal scaling where the SSE request lands on a different instance that doesn't hold the session, or clients that open the notification stream before completing initialize.","solutions":["Re-run the initialize handshake to obtain a fresh session ID before opening the SSE stream.","If running multiple instances, use sticky sessions or a shared/external session store for transports.","Detect 400 on the SSE GET and automatically re-initialize + resubscribe."],"exampleFix":"// before\nconst es = new EventSource(MCP_URL + '/mcp')\n// after\nconst es = new EventSource(MCP_URL + '/mcp', { } ) // EventSource cannot set headers; use fetch-based SSE:\n// const res = await fetch(MCP_URL + '/mcp', { headers: { 'mcp-session-id': sessionId } })","handlingStrategy":"retry","validationCode":"if (!sessionId || !(await sessionExists(sessionId))) {\n  sessionId = await initializeSession() // handshake returns fresh mcp-session-id\n}\nconst sseRes = await fetch(MCP_URL + '/mcp', { headers: { 'mcp-session-id': sessionId, accept: 'text/event-stream' } })\nif (sseRes.status === 400) { sessionId = await initializeSession(); /* retry once */ }","typeGuard":"const isInvalidSessionResponse = (res: Response): boolean =>\n  res.status === 400 && /Invalid or missing session ID/.test(res.text as unknown as string ?? '')","tryCatchPattern":"try { await openNotificationStream(sessionId) } catch { const fresh = await initializeSession(); await openNotificationStream(fresh) }","preventionTips":["Open the SSE/GET stream only after a successful initialize.","Detect 400 on GET /mcp and re-initialize + resubscribe automatically.","Behind load balancers, use sticky sessions or externalize session state."],"tags":["mcp","sse","session","http","notifications"],"backgroundTag":"mcp-session-id-invalid","analyzedSha":"3e677b1d9f7e0493c142c175560531e7ae786dce","analyzedAt":"2026-08-27T21:29:16.709Z","schemaVersion":2},"datasetVersion":"2026-08-28T00:17:15.603Z"}