{"record":{"id":"0a87434d92ba9af2","repo":"tinyhumansai/openhuman","slug":"rpc-method-error","errorCode":null,"errorMessage":"RPC ${method} error","messagePattern":"RPC (.+?) error","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"scripts/debug/harness-cache-audit.mjs","lineNumber":233,"sourceCode":"    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) => {\n        const full = path.join(current, entry.name);\n        if (entry.isDirectory()) return walk(full);\n        if (entry.isFile() && entry.name.endsWith(\".jsonl\")) out.push(full);","sourceCodeStart":215,"sourceCodeEnd":251,"githubUrl":"https://github.com/tinyhumansai/openhuman/blob/a221052e0df5b1f7598fceba7329fd1af95d6699/scripts/debug/harness-cache-audit.mjs#L215-L251","documentation":"This is the JSON-RPC application error path in harness-cache-audit.mjs: HTTP 200, body parsed, but the body carries an `error` object, and the script throws a bare `RPC <method> error` without the server's message (unlike goals-live.mjs, which includes body.error.message). The methods invoked are core.ping and openhuman.agent_chat, so the underlying fault is whatever the core's chat pipeline reported — unknown method on an old binary, invalid params, missing agent, or provider/config errors.","triggerScenarios":"`unknown method` against a core binary older than the agent_chat RPC surface; agent_chat rejecting a model_override (--model naming a model the core cannot route); the audit agent/thread referenced by thread_id not existing in that workspace; inference provider unconfigured so the turn fails server-side; feature-gated/slim core builds missing the agent domain.","commonSituations":"Stale ./target/debug/openhuman-core from an old checkout; running against a remote core of a different version; isolated temp workspace without the custom audit agent definitions; provider keys expired.","solutions":["Get the real message — reproduce the same call with curl and read body.error.message, since the script swallows it: `curl -s <url> -X POST -H 'authorization: Bearer <tok>' -H 'content-type: application/json' -d '{\"jsonrpc\":\"2.0\",\"id\":1,\"method\":\"openhuman.agent_chat\",\"params\":{...}}'`","Rebuild/spawn fresh: `cargo build --bin openhuman-core` or rerun with --spawn-core","Drop --model or set it to a model the core routes","Check GET /schema on the live core for the agent_chat surface and expected params","Inspect core logs (the script's --verbose only streams spawned-core output; for an external core tail its log file)"],"exampleFix":"# before\nnode scripts/debug/harness-cache-audit.mjs --model nonexistent-model\n# Error: RPC openhuman.agent_chat error\n\n# after — first surface the real server message, then fix accordingly\ncurl -s http://127.0.0.1:7788/rpc -X POST -H \"authorization: Bearer $TOKEN\" \\\n  -H 'content-type: application/json' \\\n  -d '{\"jsonrpc\":\"2.0\",\"id\":1,\"method\":\"openhuman.agent_chat\",\"params\":{\"prompt\":\"hi\"}}'\nnode scripts/debug/harness-cache-audit.mjs --model gpt-4.1-mini","handlingStrategy":"try-catch","validationCode":"// verify the live surface before the run: old/slim cores lack agent_chat\nconst schema = await (await fetch(coreUrl.replace(\"/rpc\", \"/schema\"), {\n  headers: { authorization: `Bearer ${token}` },\n})).json();\nconst names = JSON.stringify(schema);\nif (!names.includes(\"agent_chat\")) {\n  console.error(\"openhuman.agent_chat not present on this core — rebuild or target a current core\");\n  process.exit(2);\n}","typeGuard":"const isJsonRpcError = (body) => !!body && typeof body === \"object\" && body.error != null;","tryCatchPattern":"try {\n  result = await rpc(coreUrl, token, method, params);\n} catch (err) {\n  if (new RegExp(`RPC ${method} error$`).test(err.message)) {\n    // this script drops body.error.message — re-derive it for diagnosis\n    const probe = await fetch(coreUrl, { method: \"POST\", headers: { \"content-type\": \"application/json\", authorization: `Bearer ${token}` }, body: JSON.stringify({ jsonrpc: \"2.0\", id: 1, method, params }) });\n    const detailed = await probe.json().catch(() => null);\n    throw new Error(`${method} failed: ${detailed?.error?.message || \"no detail available\"}`);\n  }\n  throw err;\n}","preventionTips":["Rebuild the core (cargo build --bin openhuman-core) after pulling changes to RPC surfaces","Pass --model only with values the core routes; omit it to use the configured default","When this bare error appears, reproduce the call with curl to see body.error.message — the script intentionally does not print it"],"tags":["rpc","jsonrpc","version-drift","diagnostics"],"backgroundTag":null,"analyzedSha":"a221052e0df5b1f7598fceba7329fd1af95d6699","analyzedAt":"2026-08-16T12:47:06.542Z","schemaVersion":2},"datasetVersion":"2026-08-16T13:17:31.715Z"}