{"record":{"id":"8e2b5a429874ed7e","repo":"tinyhumansai/openhuman","slug":"rpc-token-not-provided-and-tokenpath-could-not","errorCode":null,"errorMessage":"RPC token not provided and ${tokenPath} could not be read. Pass --token or set OPENHUMAN_CORE_TOKEN.","messagePattern":"RPC token not provided and (.+?) could not be read\\. Pass --token or set OPENHUMAN_CORE_TOKEN\\.","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"scripts/debug/agent-prepare-context-audit.mjs","lineNumber":240,"sourceCode":"    const match = active.match(/^\\s*user_id\\s*=\\s*\"([^\"]+)\"\\s*$/m);\n    if (match?.[1])\n      return path.join(openhumanDir, \"users\", match[1], \"workspace\");\n  } catch {\n    // fall through to legacy root\n  }\n  return openhumanDir;\n}\n\nasync function readToken(opts) {\n  if (opts.token.trim()) return opts.token.trim();\n  const tokenPath = path.join(\n    opts.workspace || (await defaultWorkspace()),\n    \"core.token\",\n  );\n  try {\n    return (await readFile(tokenPath, \"utf8\")).trim();\n  } catch {\n    throw new Error(\n      `RPC token not provided and ${tokenPath} could not be read. Pass --token or set OPENHUMAN_CORE_TOKEN.`,\n    );\n  }\n}\n\nasync function rpc(coreUrl, token, method, params, timeoutMs = 600_000) {\n  const controller = new AbortController();\n  const timeout = setTimeout(() => controller.abort(), timeoutMs);\n  let res;\n  try {\n    res = await fetch(coreUrl, {\n      method: \"POST\",\n      signal: controller.signal,\n      headers: {\n        \"content-type\": \"application/json\",\n        authorization: `Bearer ${token}`,\n      },\n      body: JSON.stringify({","sourceCodeStart":222,"sourceCodeEnd":258,"githubUrl":"https://github.com/tinyhumansai/openhuman/blob/a221052e0df5b1f7598fceba7329fd1af95d6699/scripts/debug/agent-prepare-context-audit.mjs#L222-L258","documentation":"readToken() in scripts/debug/agent-prepare-context-audit.mjs resolves the RPC bearer in order: --token flag, then <workspace>/core.token where workspace is --workspace / OPENHUMAN_WORKSPACE / the auto-resolved default. If no flag/env token exists and the core.token file cannot be read, it throws this error naming the exact path it tried. The core writes core.token at the workspace root when it starts, so an unreadable file usually means no core ever ran under that workspace.","triggerScenarios":"Attaching to a running core (no --spawn-core) while: never passing --token, having no OPENHUMAN_CORE_TOKEN in env, and pointing --workspace (or OPENHUMAN_WORKSPACE) at a directory where the core never wrote core.token. Also when the default workspace resolution (OPENHUMAN_APP_ENV staging vs prod ~/.openhuman dirs) picks a different directory than the one the core actually uses.","commonSituations":"Fresh machines or CI where the audit script runs before any core has started; OPENHUMAN_APP_ENV=staging set in one shell (core writes ~/.openhuman-staging/.../core.token) but not in the shell running the script, so the auto-picked dir mismatches; typos in the --workspace path.","solutions":["Pass the token explicitly: --token <value> (or export OPENHUMAN_CORE_TOKEN)","Point --workspace at the exact workspace the core is serving — its core.token sits at that root; check the error message for the path actually tried","If the core hasn't run yet, start it once (or use --spawn-core, which generates and injects its own token) so core.token exists","Align OPENHUMAN_APP_ENV between the shell that ran the core and the shell running the audit"],"exampleFix":"# before\n$ node scripts/debug/agent-prepare-context-audit.mjs --workspace /tmp/wrong-dir\nError: RPC token not provided and /tmp/wrong-dir/core.token could not be read. ...\n\n# after\n$ node scripts/debug/agent-prepare-context-audit.mjs --workspace ~/.openhuman/users/<id>/workspace\n# or\n$ node scripts/debug/agent-prepare-context-audit.mjs --token \"$(cat ~/path/core.token)\"","handlingStrategy":"validation","validationCode":"import { readFileSync, existsSync } from \"node:fs\";\nimport path from \"node:path\";\nconst ws = process.env.OPENHUMAN_WORKSPACE || defaultWorkspace;\nconst token = process.env.OPENHUMAN_CORE_TOKEN || (existsSync(path.join(ws, \"core.token\")) ? readFileSync(path.join(ws, \"core.token\"), \"utf8\").trim() : \"\");\nif (!token) throw new Error(`no bearer: pass --token or ensure ${path.join(ws, \"core.token\")} exists (start the core once)`);","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Attach-mode runs should always resolve the token from the SAME workspace the core serves — mismatched workspace is the #1 cause","core.token is per-launch: after restarting the core, re-read it rather than caching","In automation, generate the token yourself and pass --token, or use --spawn-core which injects a fresh one"],"tags":["auth","rpc","config","token"],"backgroundTag":null,"analyzedSha":"a221052e0df5b1f7598fceba7329fd1af95d6699","analyzedAt":"2026-08-16T12:47:06.542Z","schemaVersion":2},"datasetVersion":"2026-08-16T13:17:31.715Z"}