upstash/context7 · critical
-32603
-32603
Error message
Internal server error
What it means
Catch-all around the MCP request handler in `handleMcpRequest`: any unexpected throw from `requestContext.run(nodeHandler, ...)` is logged server-side ("Error handling MCP request:") and answered with HTTP 500 and JSON-RPC code -32603 "Internal server error" — but only if headers were not already sent. The details are deliberately hidden from the client; the server log holds the real stack.
Source
Thrown at packages/mcp/src/index.ts:463
}
}
}
const context: ClientContext = {
clientIp: req.ip,
apiKey,
clientInfo: extractClientInfoFromUserAgent(req.headers["user-agent"]),
plugin,
transport: "http",
};
await requestContext.run(context, async () => {
await nodeHandler(req, res, req.body);
});
} catch (error) {
console.error("Error handling MCP request:", error);
if (!res.headersSent) {
res.status(500).json({
jsonrpc: "2.0",
error: { code: -32603, message: "Internal server error" },
id: null,
});
}
}
};
// JSON bodies and JSON-RPC error envelopes are the MCP contract only, so the
// parser and its error boundary live on the MCP router: every other route
// stays out of the parser and keeps its own response shape.
const mcpRouter = express.Router();
mcpRouter.use(express.json());
mcpRouter.use(mcpBodyErrorHandler);
mcpRouter.all("/", (req, res) => handleMcpRequest(req, res));
// OAuth-protected endpoint - requires authentication
mcpRouter.all("/oauth", (req, res) => handleMcpRequest(req, res));
app.use("/mcp", mcpRouter);View on GitHub (pinned to 80e681a507)
Solutions
- Inspect server logs for the "Error handling MCP request:" stack — the client-side message is intentionally vague
- Retry the request; transient handler faults often clear
- Update/restart the MCP server deployment
- Report with the logged stack if it reproduces on the latest version
Defensive patterns
Strategy: retry
Type guard
function isJsonRpcInternalError(body: unknown): boolean {
return typeof body === 'object' && body !== null && (body as any)?.error?.code === -32603;
} Try / catch
try {
const result = await mcpClient.callTool('get-library-docs', args);
} catch (error) {
if (/Internal server error|-32603/.test(String(error))) {
await sleep(1000);
return mcpClient.callTool('get-library-docs', args); // one idempotent retry
}
throw error;
} Prevention
- Make JSON-RPC calls idempotent so a single retry is safe
- Server operators: keep the onerror hooks wired so adapter throws reach the express catch-all and get logged
- Watch server logs for 'Error handling MCP request:' — client messages intentionally carry no detail
When it happens
Trigger: A bug in a tool implementation throwing a non-Error; a request-conversion failure inside the adapter (the code installs `onerror` hooks precisely so these reach this handler); OOM or corrupted state in a long-lived deployment.
Common situations: Server-side regressions after an SDK upgrade; resource exhaustion under load; malformed payloads that bypass earlier parsing.
Understand the failure class
- HTTP status errors: handling 4xx and 5xx responses — how to handle 4xx and 5xx responses properly.
Related errors
- -32001
- Multiline strings are not supported in MCP args
- Unsupported TOML escape \\${escape}
- Expected a TOML array for MCP args
- MCP args must be a TOML array containing only strings
AI-assisted analysis of upstash/context7@80e681a507 (2026-08-18).
Data as JSON: /api/errors/758244e7c484a7d4.
Report an issue: GitHub.