upstash/context7 · error

-32603

-32603

Error message

Internal server error

What it means

Catch-all handler in the MCP server's request wrapper: if nodeHandler (the JSON-RPC dispatch) throws an unhandled exception, the server logs it and returns a JSON-RPC internal error (code -32603, "Internal server error") with HTTP 500, unless headers were already sent. It deliberately hides internals from clients.

Solutions

  1. Check the server console logs for "Error handling MCP request:" to see the underlying exception.
  2. Fix or guard the failing tool/handler found in the stack trace; validate tool arguments with the tool's input schema.
  3. Update the MCP server/client to latest versions in case of a known bug.
  4. Retry the request after fixing; transient dependency failures can also be retried with backoff.

Example fix

// before
server.tool("search", { q: z.string() }, async ({ q }) => search(q)); // throws on upstream failure
// after
server.tool("search", { q: z.string() }, async ({ q }) => {
  try { return await search(q); }
  catch (e) { return { isError: true, content: [{ type: "text", text: String(e) }] }; }
});
Defensive patterns

Strategy: try-catch

Validate before calling

// Client-side: validate tool arguments against the schema before calling
const parsed = toolSchema.safeParse(args);
if (!parsed.success) throw new Error(`Invalid tool args: ${parsed.error.message}`);

Type guard

function isInternalRpcError(res: unknown): res is { error: { code: -32603 } } {
  return typeof res === 'object' && res !== null &&
    (res as any).error?.code === -32603;
}

Try / catch

try {
  const result = await client.callTool({ name, arguments });
} catch (e) {
  if (isInternalRpcError(e)) {
    console.error('Server-side crash; check MCP server logs');
    // retry with backoff only if the failure may be transient
  } else throw e;
}

Prevention

When it happens

Trigger: Any unexpected exception inside MCP tool call handling, session resolution, or request parsing that isn't converted to a JSON-RPC error — e.g. a tool handler throwing, a database/network call failing inside a tool, or a bug in the server itself.

Common situations: A tool crashes on bad arguments (unhandled TypeError), an upstream dependency is down, or the request context/session store throws.

Understand the failure class

Background: "This is a bug, please report it": internal invariant violations, unreachable panics, and SNH errors explained — this error's family across 47 libraries.

Related errors


AI-assisted analysis of upstash/context7@4416fb855b (2026-09-16). Data as JSON: /api/errors/758244e7c484a7d4. Report an issue: GitHub.

Appendix: source

Thrown at packages/mcp/src/index.ts:514

            return;
          }
        }

        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 4416fb855b)