{"record":{"id":"1af6c1358a9b9dac","repo":"tinyhumansai/openhuman","slug":"rpc-method-returned-non-json-http-res-status","errorCode":null,"errorMessage":"RPC ${method} returned non-JSON HTTP ${res.status}: ${bodyText.slice(0, 200)}","messagePattern":"RPC (.+?) returned non-JSON HTTP (.+?): (.+?)","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"scripts/debug/agent-prepare-context-audit.mjs","lineNumber":277,"sourceCode":"        jsonrpc: \"2.0\",\n        id: `apc-${Date.now()}-${Math.random().toString(16).slice(2)}`,\n        method,\n        params,\n      }),\n    });\n  } catch (err) {\n    if (err?.name === \"AbortError\")\n      throw new Error(`RPC ${method} timed out after ${timeoutMs}ms`);\n    throw err;\n  } finally {\n    clearTimeout(timeout);\n  }\n  const bodyText = await res.text();\n  let body;\n  try {\n    body = JSON.parse(bodyText);\n  } catch {\n    throw new Error(\n      `RPC ${method} returned non-JSON HTTP ${res.status}: ${bodyText.slice(0, 200)}`,\n    );\n  }\n  if (!res.ok) throw new Error(`RPC ${method} HTTP ${res.status}`);\n  if (body.error)\n    throw new Error(\n      `RPC ${method} error: ${JSON.stringify(body.error).slice(0, 300)}`,\n    );\n  return body.result;\n}\n\n// ── Transcript reading ──────────────────────────────────────────────────────\n\nasync function walkJsonl(dir) {\n  const out = [];\n  async function walk(current) {\n    let entries;\n    try {","sourceCodeStart":259,"sourceCodeEnd":295,"githubUrl":"https://github.com/tinyhumansai/openhuman/blob/a221052e0df5b1f7598fceba7329fd1af95d6699/scripts/debug/agent-prepare-context-audit.mjs#L259-L295","documentation":"After fetch resolves, rpc() in scripts/debug/agent-prepare-context-audit.mjs reads the body as text and attempts JSON.parse; on failure it throws 'RPC <method> returned non-JSON HTTP <status>' with the first 200 characters of the body. It means the endpoint answered — but with HTML/plain text (proxy error page, auth-portal redirect, directory listing) rather than a JSON-RPC response.","triggerScenarios":"--core-url / OPENHUMAN_CORE_RPC_URL pointing at a URL that is not the JSON-RPC endpoint: the bare host root (http://127.0.0.1:7788 without /rpc), a port serving a different service (Vite dev server returning HTML), or a corporate proxy intercepting with an HTML block page. The HTTP status in the message (200, 502, 302-followed-200, ...) hints at which.","commonSituations":"Forgetting the /rpc suffix when hand-writing --core-url; port 7788 already occupied by another process so the script talks to the wrong server; OPENHUMAN_CORE_RPC_URL inherited from a different tool that expects a base URL rather than the full /rpc path; VPN/proxy rewriting localhost-less URLs.","solutions":["Use the full endpoint including /rpc: http://127.0.0.1:7788/rpc (the script's default)","Check what actually answers: curl -i the URL and look at Content-Type — JSON-RPC answers application/json","Free or change the port if another service occupies it (the spawned-core path derives the port from --core-url)","Unset OPENHUMAN_CORE_RPC_URL if it carries a stale/wrong endpoint from another tooling"],"exampleFix":"# before\n$ node scripts/debug/agent-prepare-context-audit.mjs --core-url http://127.0.0.1:7788\nError: RPC core.ping returned non-JSON HTTP 200: <!doctype html>...\n\n# after\n$ node scripts/debug/agent-prepare-context-audit.mjs --core-url http://127.0.0.1:7788/rpc","handlingStrategy":"validation","validationCode":"// Pre-flight: the endpoint must speak JSON before any RPC\nconst res = await fetch(coreUrl, { method: \"POST\", headers: { \"content-type\": \"application/json\" }, body: JSON.stringify({ jsonrpc: \"2.0\", id: 1, method: \"core.ping\", params: {} }) });\nconst ct = res.headers.get(\"content-type\") || \"\";\nif (!ct.includes(\"json\")) throw new Error(`${coreUrl} is not a JSON-RPC endpoint (content-type: ${ct || \"none\"}) — did you mean ${coreUrl.replace(/\\/?$/, \"\")}/rpc ?`);","typeGuard":null,"tryCatchPattern":"try {\n  return await rpc(coreUrl, token, method, params);\n} catch (e) {\n  if (/returned non-JSON/.test(e.message)) {\n    throw new Error(`Wrong endpoint? ${coreUrl} must end with /rpc and point at openhuman-core. Original: ${e.message}`);\n  }\n  throw e;\n}","preventionTips":["Always write the full path http://127.0.0.1:7788/rpc — the /rpc suffix is mandatory","curl -i the endpoint once when setting up a new environment; content-type: application/json is the tell","Audit inherited OPENHUMAN_CORE_RPC_URL values — other tools may expect a base URL instead of the RPC path"],"tags":["rpc","http","config","url"],"backgroundTag":null,"analyzedSha":"a221052e0df5b1f7598fceba7329fd1af95d6699","analyzedAt":"2026-08-16T12:47:06.542Z","schemaVersion":2},"datasetVersion":"2026-08-16T13:17:31.715Z"}