can1357/oh-my-pi · error · SyntaxError
Malformed JSON-RPC response
Error message
Malformed JSON-RPC response
What it means
The HTTP response to a JSON-RPC POST was 2xx but its parsed JSON body is not a valid JSON-RPC 2.0 response — missing jsonrpc:"2.0" and neither result nor error. The transport throws SyntaxError("Malformed JSON-RPC response"), later normalized into a decode-stage MCPTransportError.
Source
Thrown at packages/coding-agent/src/mcp/transports/http.ts:503
message: `HTTP ${response.status}: ${text}${suffix}`,
retryable: response.status === 404 || response.status === 502 || response.status === 503,
code: response.status,
traceId,
});
}
const contentType = response.headers.get("Content-Type") ?? "";
// Handle SSE response
if (contentType.includes("text/event-stream")) {
return this.#parseSSEResponse<T>(response, id, options);
}
stage = "decode";
// Handle JSON response
const result: unknown = await response.json();
if (!isRecord(result) || result.jsonrpc !== "2.0" || (!("result" in result) && !("error" in result))) {
throw new SyntaxError("Malformed JSON-RPC response");
}
if (result.error !== undefined) {
if (
!isRecord(result.error) ||
typeof result.error.code !== "number" ||
typeof result.error.message !== "string"
) {
throw new SyntaxError("Malformed JSON-RPC error response");
}
throw createMCPJsonRpcError(
"http",
{ code: result.error.code, message: result.error.message, data: result.error.data },
traceId,
);
}
return result.result as T;
} catch (error) {View on GitHub (pinned to 9690622007)
Solutions
- Log the raw response body to see what the server actually returned
- Verify the URL is the MCP JSON-RPC endpoint, not a REST or health-check route
- Upgrade/align the MCP server so responses follow JSON-RPC 2.0 ({jsonrpc:"2.0", id, result|error})
- Check for proxies/middleware that wrap or replace response bodies
Example fix
// before
// server returns {"ok":true,"data":{...}} → Malformed JSON-RPC response
// after
// server returns {"jsonrpc":"2.0","id":1,"result":{...}} — fix server or point client at the correct /mcp endpoint Defensive patterns
Strategy: type-guard
Validate before calling
// Validate a sample response shape during integration:
const body = await (await fetch(url, { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ jsonrpc: "2.0", id: 1, method: "ping" }) })).json();
if (body?.jsonrpc !== "2.0") throw new Error("endpoint does not speak JSON-RPC 2.0"); Type guard
function isJsonRpcResponse(v: unknown): v is { jsonrpc: "2.0"; id: unknown; result?: unknown; error?: unknown } {
return typeof v === "object" && v !== null && (v as any).jsonrpc === "2.0" && ("result" in v || "error" in v);
} Try / catch
try {
await transport.request(method, params);
} catch (err) {
if (err instanceof SyntaxError && err.message === "Malformed JSON-RPC response") {
log.error("non-JSON-RPC endpoint or rewriting proxy", { url });
} else throw err;
} Prevention
- Verify the URL is the JSON-RPC MCP endpoint during onboarding
- Check for gateways that replace error bodies with custom JSON
- Keep server and client protocol versions aligned
- Log raw bodies when introducing a new server
When it happens
Trigger: Response Content-Type was application/json but the body is arbitrary JSON: a plain error object, an HTML/error page served with a JSON content type, a proxy's JSON envelope, or a non-JSON-RPC API at the configured URL.
Common situations: Pointing the client at a REST endpoint instead of the MCP JSON-RPC endpoint; an API gateway rewriting error bodies; server bug returning unwrapped results; wrong protocol version speaking a different envelope.
Understand the failure class
- Parsing and encoding errors: unexpected token, malformed input — why parsers reject input and how to find the real culprit.
Related errors
- Malformed JSON-RPC error response
- MCP error: ${response.error.message}
- MCP request failed: ${response.status} ${response.statusText
- Failed to parse MCP response
- HTTP ${response.status}: ${text}${suffix}
AI-assisted analysis of can1357/oh-my-pi@9690622007 (2026-08-31).
Data as JSON: /api/errors/ac75dc0e788125c2.
Report an issue: GitHub.