paperclipai/paperclip · error · ToolGatewayHttpError
mcp_remote_invalid_json
mcp_remote_invalid_json
Error message
Remote MCP server returned invalid JSON
What it means
Remote MCP response body could not be parsed as JSON (or the content-type Negotiation failed in parseMcpHttpResponseBody). The connection is marked unhealthy and a 502 mcp_remote_invalid_json is thrown with the execution context; the upstream server returned a malformed or non-JSON payload such as an HTML error page.
Solutions
- The remote MCP server returned malformed JSON. Verify the endpoint speaks MCP/JSON-RPC and inspect the raw response.
Defensive patterns
Strategy: try-catch
When it happens
Trigger: Thrown at server/src/services/tool-gateway.ts:3118 when the library encounters an invalid state.
Common situations: See trigger scenarios.
Understand the failure class
- Parsing and encoding errors: unexpected token, malformed input — why parsers reject input and how to find the real culprit.
AI-assisted analysis of paperclipai/paperclip@3f1d897a7c (2026-08-18).
Data as JSON: /api/errors/c5e5852025bd03f5.
Report an issue: GitHub.
Appendix: source
Thrown at server/src/services/tool-gateway.ts:4150
refHash: input.refHash,
versionSelector: String(versionSelector),
resolvedVersion: -1,
};
}
}
async function connectedCredentialVersionSnapshots(
connection: typeof toolConnections.$inferSelect,
grant: typeof connectionGrants.$inferSelect,
options: { requireResolved: boolean },
): Promise<{
headerCredentialVersions: ConnectedCredentialVersionSnapshot[];
credentialSecretVersions: ConnectedCredentialVersionSnapshot[];
}> {
const headerCredentialVersions: ConnectedCredentialVersionSnapshot[] = [];
const credentialSecretVersions: ConnectedCredentialVersionSnapshot[] = [];
for (const ref of connection.credentialRefs ?? []) {
if (ref.placement !== "header" && ref.placement !== "url") continue;
const typedRef = ref as McpConnectionCredentialRef;
const grantRef = grantRefForCredential(grant, typedRef);
if (!grantRef) continue;
const configPath =
typedRef.placement === "url"
? REMOTE_URL_SECRET_CONFIG_PATH
: `credentials.${typedRef.name}`;
headerCredentialVersions.push(
await resolveConnectedCredentialVersion(connection, {
secretId: grantRef.secretId,
versionSelector: grantRef.versionSelector,
configPath,
refHash: credentialVersionRefHash({
kind: typedRef.placement === "url" ? "url" : "header",
name: typedRef.name,
secretId: grantRef.secretId,
placement: typedRef.placement,View on GitHub (pinned to 3f1d897a7c)