{"record":{"id":"24bd489337749269","repo":"tinyhumansai/openhuman","slug":"rpc-method-returned-non-json-http-res-status-24bd48","errorCode":null,"errorMessage":"RPC ${method} returned non-JSON HTTP ${res.status}","messagePattern":"RPC (.+?) returned non-JSON HTTP (.+?)","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"scripts/debug/harness-cache-audit.mjs","lineNumber":227,"sourceCode":"        id: `audit-${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    }\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(`RPC ${method} returned non-JSON HTTP ${res.status}`);\n  }\n  if (!res.ok) {\n    throw new Error(`RPC ${method} HTTP ${res.status}`);\n  }\n  if (body.error) {\n    throw new Error(`RPC ${method} error`);\n  }\n  return body.result;\n}\n\nasync function walkJsonl(dir) {\n  const out = [];\n  async function walk(current) {\n    let entries;\n    try {\n      entries = await readdir(current, { withFileTypes: true });\n    } catch {\n      return;","sourceCodeStart":209,"sourceCodeEnd":245,"githubUrl":"https://github.com/tinyhumansai/openhuman/blob/a221052e0df5b1f7598fceba7329fd1af95d6699/scripts/debug/harness-cache-audit.mjs#L209-L245","documentation":"After the fetch completes, harness-cache-audit's rpc() JSON.parses the response text and throws this error when parsing fails. The core's /rpc endpoint always emits JSON, so a non-JSON body indicates the request terminated at some other HTTP speaker — wrong port/path, a proxy error page, or a server crash mid-body. Note this script's message omits the body snippet that goals-live.mjs includes, so you get only the status code.","triggerScenarios":"--core-url or inherited OPENHUMAN_CORE_RPC_URL pointing at the Vite dev server (5173), a Docker proxy, or a cloud endpoint that returns HTML; missing /rpc path so the root handler answers; proxy env (HTTP_PROXY/HTTPS_PROXY) capturing the loopback fetch; the external core crashing between headers and body.","commonSituations":"Default URL http://127.0.0.1:7788/rpc occupied by a different service after a reboot; env exported in a shared dotfile for a remote core no longer running; VPN client intercepting loopback traffic.","solutions":["Reproduce outside the script: `curl -sv <core-url> -X POST -H 'content-type: application/json' -d '{}'` and look at what answers","Fix --core-url to the real core endpoint including /rpc (default http://127.0.0.1:7788/rpc)","Set NO_PROXY/no_proxy for 127.0.0.1 and retry","Confirm the core process is up: `curl -s http://127.0.0.1:7788/health`","If the culprit server is stale, kill it or let --spawn-core pick a free port"],"exampleFix":"# before\nnode scripts/debug/harness-cache-audit.mjs --core-url http://127.0.0.1:5173/rpc\n# Error: RPC core.ping returned non-JSON HTTP 200\n\n# after\nnode scripts/debug/harness-cache-audit.mjs --core-url http://127.0.0.1:7788/rpc","handlingStrategy":"validation","validationCode":"const probe = await fetch(coreUrl, { method: \"POST\", headers: { \"content-type\": \"application/json\" }, body: \"{\\\"jsonrpc\\\":\\\"2.0\\\",\\\"id\\\":1,\\\"method\\\":\\\"core.ping\\\",\\\"params\\\":{}}\" });\nconst text = await probe.text();\nif (!probe.ok || !JSON.parse(text.slice(0, 1) ? text : \"null\")) {\n  console.error(`${coreUrl} did not answer JSON (HTTP ${probe.status})`);\n  process.exit(2);\n}","typeGuard":"const isJsonBody = (text) => { try { JSON.parse(text); return true; } catch { return false; } };","tryCatchPattern":"let body;\ntry {\n  body = JSON.parse(bodyText);\n} catch {\n  // enrich the bare script error with the body head — this script omits it\n  throw new Error(`non-JSON HTTP ${res.status} from ${coreUrl}; head: ${bodyText.slice(0, 120)}`);\n}","preventionTips":["Probe the endpoint with a one-line curl before first use in a new environment","Dedicate a port to the core; never reuse dev-server ports","Export NO_PROXY=127.0.0.1 wherever a system proxy is configured"],"tags":["rpc","json","network","configuration"],"backgroundTag":null,"analyzedSha":"a221052e0df5b1f7598fceba7329fd1af95d6699","analyzedAt":"2026-08-16T12:47:06.542Z","schemaVersion":2},"datasetVersion":"2026-08-16T13:17:31.715Z"}