{"record":{"id":"99303d0989ccf4ef","repo":"tinyhumansai/openhuman","slug":"rpc-token-not-found-at-tokenpath-pass-token","errorCode":null,"errorMessage":"RPC token not found at ${tokenPath}. Pass --token or set OPENHUMAN_CORE_TOKEN.","messagePattern":"RPC token not found at (.+?)\\. Pass --token or set OPENHUMAN_CORE_TOKEN\\.","errorType":"validation","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"scripts/debug/goals-live.mjs","lineNumber":169,"sourceCode":"    const active = await readFile(path.join(dir, \"active_user.toml\"), \"utf8\");\n    const match = active.match(/^\\s*user_id\\s*=\\s*\"([^\"]+)\"\\s*$/m);\n    if (match?.[1]) return path.join(dir, \"users\", match[1], \"workspace\");\n  } catch {\n    // fall through\n  }\n  return dir;\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 found at ${tokenPath}. 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 timer = 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":151,"sourceCodeEnd":187,"githubUrl":"https://github.com/tinyhumansai/openhuman/blob/a221052e0df5b1f7598fceba7329fd1af95d6699/scripts/debug/goals-live.mjs#L151-L187","documentation":"readToken() in goals-live.mjs resolves the RPC bearer in order: --token, then the OPENHUMAN_CORE_TOKEN env var (seeded into opts at startup), then <workspace>/core.token on disk. If all three fail — no flag, no env, and the core.token file unreadable — it throws with the path it tried. The core's HTTP RPC endpoint requires this per-launch hex bearer, so without it every request would 401 anyway; the script fails early instead.","triggerScenarios":"Running against an external core (no --spawn-core) whose workspace has no core.token because the core was started with OPENHUMAN_CORE_TOKEN set to a value never written to disk; passing --workspace pointing at a fresh/wrong directory; OPENHUMAN_APP_ENV=staging making the default dir ~/.openhuman-staging while the token lives in ~/.openhuman; the core simply not running/initialized in the resolved workspace.","commonSituations":"Core started standalone via `./target/debug/openhuman-core serve` with a custom token; multiple workspaces/profiles and the script picking the empty one; staging vs prod directory confusion; first run on a machine where the app has never booted the core.","solutions":["Pass the bearer explicitly: `--token <value>` or `OPENHUMAN_CORE_TOKEN=<value> node ...`","Point at the workspace that actually holds core.token: `--workspace ~/.openhuman/users/<id>/workspace` (or ~/.openhuman-staging/... when OPENHUMAN_APP_ENV=staging)","Let the script generate and inject its own token with `--spawn-core` (startCore mints `goals-<hex>` and passes OPENHUMAN_CORE_TOKEN to the child)","Verify the file exists: `ls <workspace>/core.token` — if the core wrote it elsewhere, align --workspace with the core's OPENHUMAN_WORKSPACE"],"exampleFix":"// before\nnode scripts/debug/goals-live.mjs --core-url http://127.0.0.1:7788/rpc\n# Error: RPC token not found at /home/me/.openhuman/.../core.token ...\n\n// after\nOPENHUMAN_CORE_TOKEN=$(cat ~/.openhuman/users/<id>/workspace/core.token) \\\n  node scripts/debug/goals-live.mjs --core-url http://127.0.0.1:7788/rpc","handlingStrategy":"validation","validationCode":"import { access } from \"node:fs/promises\";\n\nasync function tokenResolvable(opts) {\n  if (opts.token?.trim()) return true;\n  if (process.env.OPENHUMAN_CORE_TOKEN?.trim()) return true;\n  const ws = opts.workspace || process.env.OPENHUMAN_WORKSPACE || defaultWorkspaceGuess();\n  try {\n    await access(path.join(ws, \"core.token\"));\n    return true;\n  } catch {\n    return false;\n  }\n}\nif (!(await tokenResolvable(opts))) {\n  console.error(\"no RPC bearer: pass --token, export OPENHUMAN_CORE_TOKEN, or boot the core once\");\n  process.exit(2);\n}","typeGuard":null,"tryCatchPattern":"try {\n  token = await readToken(opts);\n} catch (err) {\n  if (/RPC token not found/.test(err.message)) {\n    // recover: spawn a core that owns its token instead of failing\n    opts.spawnCore = true;\n    ({ token } = await startCore(opts));\n  } else throw err;\n}","preventionTips":["Boot the core once (app or `openhuman-core serve`) so <workspace>/core.token exists before running external-core audits","Use --spawn-core when you do not care about a specific core instance — it mints and injects the token for you","Remember OPENHUMAN_APP_ENV=staging switches the default search root to ~/.openhuman-staging"],"tags":["auth","rpc","token","filesystem"],"backgroundTag":null,"analyzedSha":"a221052e0df5b1f7598fceba7329fd1af95d6699","analyzedAt":"2026-08-16T12:47:06.542Z","schemaVersion":2},"datasetVersion":"2026-08-16T13:17:31.715Z"}