{"record":{"id":"d5b278e13d479855","repo":"vercel/ai","slug":"protocol-error-received-a-response-for-an-unknown","errorCode":null,"errorMessage":"Protocol error: Received a response for an unknown message ID: ${JSON.stringify(response)}","messagePattern":"Protocol error: Received a response for an unknown message ID: (.+?)","errorType":"exception","errorClass":"MCPClientError","httpStatus":null,"severity":"error","filePath":"packages/mcp/src/tool/mcp-client.ts","lineNumber":1523,"sourceCode":"  }\n\n  private onResponse(response: JSONRPCResponse | JSONRPCError): void {\n    if (response.id == null) {\n      this.onError(\n        new MCPClientError({\n          message: `Protocol error: Received a response without a message ID: ${JSON.stringify(\n            response,\n          )}`,\n        }),\n      );\n      return;\n    }\n\n    const messageId = Number(response.id);\n    const handler = this.responseHandlers.get(messageId);\n\n    if (handler === undefined) {\n      throw new MCPClientError({\n        message: `Protocol error: Received a response for an unknown message ID: ${JSON.stringify(\n          response,\n        )}`,\n      });\n    }\n\n    this.responseHandlers.delete(messageId);\n\n    handler(\n      'result' in response\n        ? response\n        : new MCPClientError({\n            message: response.error.message,\n            code: response.error.code,\n            data: response.error.data,\n            cause: response.error,\n          }),\n    );","sourceCodeStart":1505,"sourceCodeEnd":1541,"githubUrl":"https://github.com/vercel/ai/blob/69428b1f8b037e4d118fb4853428d5c4e620493c/packages/mcp/src/tool/mcp-client.ts#L1505-L1541","documentation":"The transport received a JSON-RPC response whose id has no registered pending handler in this.responseHandlers. This breaks the JSON-RPC request/response correlation, so DefaultMCPClient throws MCPClientError. It almost always means the response came from a different/previous connection, the client reconnected (losing pending handlers), or the server sent a malformed or duplicate response.","triggerScenarios":"Server sends a response with an id never requested (duplicate/replayed message), the client's transport reconnected and cleared responseHandlers while the server still replies to old ids, an id type mismatch (e.g. string vs number id such that Number(response.id) doesn't match the registered key), or responses interleave across two connections to the same server.","commonSituations":"Proxy/load-balanced MCP endpoints routing responses from a different session; server restarts mid-request; custom transports or middleware rewriting message ids; long-running requests outliving a reconnect after a network blip.","solutions":["Ensure a single connection per client: recreate the MCPClient (or call connect again) after any disconnect instead of reusing a stale transport","Verify no proxy or middleware rewrites or duplicates JSON-RPC message ids; log raw messages to confirm the id actually was requested","Check that request timeouts/reconnect logic tears down pending handlers together with the connection, so stale responses can't be matched to a fresh session","Update the MCP server/SDK if it is known to send malformed ids (e.g. string ids that don't parse to the same number)"],"exampleFix":"// before\nconst client = await createMCPClient({ transport }); // reused after reconnect\n// after\nclient.close();\nconst client = await createMCPClient({ transport: freshTransport }); // new session per connect","handlingStrategy":"try-catch","validationCode":"// ensure exactly one active client per server session before issuing requests\nif (activeClient && activeClientClosed) { activeClient = await createMCPClient({ transport: newTransport() }); }","typeGuard":"function isUnknownMessageIdError(e: unknown): boolean {\n  return MCPClientError.isInstance(e) && e.message.includes('unknown message ID');\n}","tryCatchPattern":"try {\n  result = await client.callTool(args);\n} catch (error) {\n  if (isUnknownMessageIdError(error)) {\n    await client.close();\n    client = await createMCPClient({ transport: newTransport() }); // fresh session, then retry once\n  } else throw error;\n}","preventionTips":["Recreate the client after any disconnect; never reuse a transport across reconnects","Avoid proxies/middleware that duplicate or rewrite JSON-RPC ids","Log raw JSON-RPC traffic when debugging protocol mismatches"],"tags":["json-rpc","protocol","state-corruption"],"backgroundTag":"unknown-message-id","analyzedSha":"69428b1f8b037e4d118fb4853428d5c4e620493c","analyzedAt":"2026-08-30T12:32:21.016Z","schemaVersion":2},"datasetVersion":"2026-08-30T13:17:10.514Z"}