rohitg00/ai-engineering-from-scratch · error · RpcProblem

-32600

-32600

Error message

Invalid Request

What it means

The server rejects an incoming JSON-RPC message whose envelope is not a valid 2.0 request: jsonrpc must be the exact string '2.0' and method must be a string. This is the JSON-RPC 2.0 spec's Invalid Request code (-32600), thrown by validateRequest before any handler runs.

Source

Thrown at phases/13-tools-and-protocols/07-building-an-mcp-server/code/main.ts:160

  if (data !== undefined) error.data = data;
  return { jsonrpc: "2.0", id, error };
}

function complete(
  payload: JsonObject,
  cache?: { ttlMs: number; cacheScope: "private" | "public" },
): JsonObject {
  return {
    resultType: "complete",
    ...payload,
    ...(cache ?? {}),
    _meta: { [SERVER_INFO_KEY]: { ...SERVER_INFO } },
  };
}

function validateRequest(message: JsonRpcRequest): void {
  if (message.jsonrpc !== "2.0" || typeof message.method !== "string") {
    throw new RpcProblem(-32600, "Invalid Request");
  }
  const requestId: unknown = message.id;
  if (requestId !== undefined && !isValidRequestId(requestId)) {
    throw new RpcProblem(-32600, "id must be a string or integer");
  }
  const params = message.params;
  if (!params || typeof params !== "object" || Array.isArray(params)) {
    throw new RpcProblem(-32602, "params must be an object");
  }
  const meta = params._meta;
  if (!meta || typeof meta !== "object" || Array.isArray(meta)) {
    throw new RpcProblem(-32602, "params._meta is required");
  }
  const requested = meta[VERSION_KEY];
  if (typeof requested !== "string") {
    throw new RpcProblem(-32602, `${VERSION_KEY} is required`);
  }
  if (!SUPPORTED_VERSIONS.includes(requested)) {

View on GitHub (pinned to 39ea8a1c6d)

Solutions

  1. Set jsonrpc:'2.0' and a string method on every request sent to dispatch
  2. Log the raw message before dispatch to see exactly which field is wrong
  3. If writing a client, centralize envelope construction in one helper so the field can never be missed

Example fix

// before
dispatch({ id: 1, method: 'initialize', params: { _meta: {} } });
// after
dispatch({ jsonrpc: '2.0', id: 1, method: 'initialize', params: { _meta: {} } });
Defensive patterns

Strategy: validation

Validate before calling

function isValidEnvelope(m: unknown): boolean { 
  return typeof m === 'object' && m !== null 
    && (m as any).jsonrpc === '2.0' 
    && typeof (m as any).method === 'string'; 
} 
if (!isValidEnvelope(msg)) throw new Error('bad envelope');

Type guard

function isJsonRpcRequest(m: unknown): m is { jsonrpc: '2.0'; method: string } { 
  return typeof m === 'object' && m !== null && (m as Record<string, unknown>).jsonrpc === '2.0' 
    && typeof (m as Record<string, unknown>).method === 'string'; 
}

Try / catch

try { dispatch(msg); } catch (e) { if (e instanceof RpcProblem && e.code === -32600) fixEnvelopeAndRetry(); else throw e; }

Prevention

When it happens

Trigger: dispatch() receives a message with jsonrpc:'1.0' or missing, a numeric method like method:42, or a notification-shaped payload with a non-string method field.

Common situations: Hand-rolled stdio clients forgetting the jsonrpc:'2.0' field, JSON pipelines that mangle keys, or tests reusing JSON-RPC 1.0 style payloads ({id, method, params} without the version field).

Related errors


AI-assisted analysis of rohitg00/ai-engineering-from-scratch@39ea8a1c6d (2026-08-26). Data as JSON: /api/errors/00e6c4eb76e7f80c. Report an issue: GitHub.