{"record":{"id":"ed171742b96d9f29","repo":"tinyhumansai/openhuman","slug":"rpc-method-http-res-status-ed1717","errorCode":null,"errorMessage":"RPC ${method} HTTP ${res.status}","messagePattern":"RPC (.+?) HTTP (.+?)","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"scripts/debug/harness-cache-audit.mjs","lineNumber":230,"sourceCode":"      }),\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;\n    }\n    await Promise.all(\n      entries.map(async (entry) => {","sourceCodeStart":212,"sourceCodeEnd":248,"githubUrl":"https://github.com/tinyhumansai/openhuman/blob/a221052e0df5b1f7598fceba7329fd1af95d6699/scripts/debug/harness-cache-audit.mjs#L212-L248","documentation":"When the response body parses as JSON but res.ok is false, harness-cache-audit's rpc() throws this transport-level status error (the JSON-RPC-level error case is separate and even less informative). Reaching this branch means an HTTP server answered with JSON and a non-2xx status — in practice almost always 401 authentication on the core's /rpc endpoint, or 404 from a wrong path.","triggerScenarios":"401 from a stale/wrong bearer (core restarted, per-launch token rotated, staging token used against prod workspace); 404 from --core-url missing the /rpc suffix; 403 from a reverse proxy; 502/503 while the core restarts under load.","commonSituations":"core.token read from a workspace whose core has since relaunched with a new token; mixed OPENHUMAN_CORE_TOKEN in the environment overriding the file-based one invisibly; URL pasted from the health endpoint docs rather than the RPC one.","solutions":["401 → pass the current token: `--token $(cat <workspace>/core.token)` or refresh OPENHUMAN_CORE_TOKEN; or use --spawn-core","404 → include the /rpc path: http://127.0.0.1:7788/rpc","Verify with curl including the Authorization header to see the raw status","Check for proxy layers (corporate proxy, service mesh) adding their own status codes"],"exampleFix":"# before\nnode scripts/debug/harness-cache-audit.mjs --token stale-token-from-yesterday\n# Error: RPC openhuman.agent_chat HTTP 401\n\n# after\nnode scripts/debug/harness-cache-audit.mjs --token $(cat ~/.openhuman/users/<id>/workspace/core.token)","handlingStrategy":"validation","validationCode":"const probe = await fetch(coreUrl, {\n  method: \"POST\",\n  headers: { \"content-type\": \"application/json\", authorization: `Bearer ${token}` },\n  body: JSON.stringify({ jsonrpc: \"2.0\", id: 1, method: \"core.ping\", params: {} }),\n});\nif (probe.status === 401 || probe.status === 404) {\n  console.error(`endpoint check failed with ${probe.status} — ${probe.status === 401 ? \"refresh the bearer\" : \"fix the URL (include /rpc)\"}`);\n  process.exit(2);\n}","typeGuard":"const isHttpStatusError = (err) => /HTTP [45]\\d{2}$/.test(err?.message || \"\");","tryCatchPattern":"try {\n  return await rpc(coreUrl, token, method, params);\n} catch (err) {\n  if (/HTTP 401$/.test(err.message)) {\n    token = (await readFile(path.join(workspace, \"core.token\"), \"utf8\")).trim(); // re-read after core restart\n    return await rpc(coreUrl, token, method, params);\n  }\n  throw err;\n}","preventionTips":["Re-read core.token whenever the core restarts — the bearer is per-launch","Always include the /rpc suffix in the URL","Prefer --spawn-core for ephemeral audits to eliminate stale-bearer failure modes"],"tags":["rpc","http","auth","configuration"],"backgroundTag":null,"analyzedSha":"a221052e0df5b1f7598fceba7329fd1af95d6699","analyzedAt":"2026-08-16T12:47:06.542Z","schemaVersion":2},"datasetVersion":"2026-08-16T13:17:31.715Z"}