{"record":{"id":"1b00dfb8b817795b","repo":"tinyhumansai/openhuman","slug":"spawned-core-exited-with-child-exitcode-stder","errorCode":null,"errorMessage":"spawned core exited with ${child.exitCode}\n${stderrFn()}","messagePattern":"spawned core exited with (.+?)\n(.+?)","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"scripts/debug/goals-live.mjs","lineNumber":393,"sourceCode":"      stdio: opts.verbose ? [\"ignore\", \"inherit\", \"inherit\"] : [\"ignore\", \"ignore\", \"pipe\"],\n    },\n  );\n  let stderr = \"\";\n  if (child.stderr) {\n    child.stderr.on(\"data\", (c) => {\n      stderr += c.toString();\n      if (stderr.length > 8000) stderr = stderr.slice(-8000);\n    });\n  }\n  await waitForCore(opts.coreUrl, token, child, () => stderr);\n  return { child, token };\n}\n\nasync function waitForCore(coreUrl, token, child, stderrFn) {\n  const deadline = Date.now() + 180_000;\n  while (Date.now() < deadline) {\n    if (child.exitCode !== null)\n      throw new Error(`spawned core exited with ${child.exitCode}\\n${stderrFn()}`);\n    try {\n      await rpc(coreUrl, token, \"core.ping\", {}, 10_000);\n      return;\n    } catch {\n      await new Promise((r) => setTimeout(r, 750));\n    }\n  }\n  throw new Error(`timed out waiting for core at ${coreUrl}\\n${stderrFn()}`);\n}\n\nasync function stopChild(child) {\n  if (child.exitCode !== null || child.signalCode !== null) return;\n  child.kill(\"SIGTERM\");\n  const exited = await Promise.race([\n    once(child, \"exit\").then(() => true),\n    new Promise((r) => setTimeout(() => r(false), 5000)),\n  ]);\n  if (exited) return;","sourceCodeStart":375,"sourceCodeEnd":411,"githubUrl":"https://github.com/tinyhumansai/openhuman/blob/a221052e0df5b1f7598fceba7329fd1af95d6699/scripts/debug/goals-live.mjs#L375-L411","documentation":"waitForCore() polls core.ping every 750 ms for up to 180 s while a freshly spawned `cargo run --bin openhuman-core -- run --jsonrpc-only` child boots. If the child process exits before ever answering a ping, this error reports the exit code plus the last 8 KB of captured stderr. It means the core failed during startup, not that it was slow.","triggerScenarios":"Rust compile error or panic at core startup (exit 101 with compiler/panic output in stderr); port already in use when --core-url was passed explicitly (or OPENHUMAN_CORE_RPC_URL set), because startCore only auto-picks a free port when the URL was NOT explicit; env vars like OPENHUMAN_WORKSPACE pointing somewhere unwritable; cargo not finding the manifest (wrong cwd, though the script resolves repo root).","commonSituations":"Developer has a core already listening on 7788 and exports OPENHUMAN_CORE_RPC_URL=http://127.0.0.1:7788/rpc, so the spawned child cannot bind and exits; a mid-rebase tree that does not compile; stale target/ artifacts confusing the build; workspace permissions in a read-only mount.","solutions":["Read the stderr tail in the message — it is the actual compiler/runtime failure","If stderr shows 'address already in use', drop --core-url / unset OPENHUMAN_CORE_RPC_URL so the script picks a free port, or stop the existing core","Prebuild to surface compile errors separately: `cargo build --bin openhuman-core`, fix, then rerun","Rerun with --verbose to stream the child's stdout/stderr live instead of the tail"],"exampleFix":"# before: explicit URL collides with a running core\nOPENHUMAN_CORE_RPC_URL=http://127.0.0.1:7788/rpc node scripts/debug/goals-live.mjs --spawn-core\n# Error: spawned core exited with 1 ... address already in use\n\n# after: let the script pick a free port\nnode scripts/debug/goals-live.mjs --spawn-core","handlingStrategy":"validation","validationCode":"// before spawning: ensure the port from the URL is free, or drop the explicit URL\nimport { createConnection } from \"node:net\";\nconst port = Number(new URL(coreUrl).port || 7788);\nconst busy = await new Promise((r) => {\n  const s = createConnection({ port, host: \"127.0.0.1\" });\n  s.on(\"connect\", () => { s.destroy(); r(true); });\n  s.on(\"error\", () => r(false));\n});\nif (busy && opts.coreUrlExplicit) {\n  console.error(`port ${port} occupied — unset OPENHUMAN_CORE_RPC_URL or stop the running core`);\n  process.exit(2);\n}","typeGuard":null,"tryCatchPattern":"try {\n  await waitForCore(coreUrl, token, child, stderrFn);\n} catch (err) {\n  if (/spawned core exited/.test(err.message)) {\n    // run `cargo build --bin openhuman-core` once to surface the compile error directly\n    throw new Error(`core failed to start; build it separately to see the error\\n${err.message}`);\n  }\n  throw err;\n}","preventionTips":["Do not export OPENHUMAN_CORE_RPC_URL globally — it silently forces --spawn-core onto a fixed port","Compile first (`cargo build --bin openhuman-core`) so spawn failures are runtime, not compiler, errors","Use --verbose whenever a spawned core dies so the failure is streamed, not a tail"],"tags":["process","spawn","rust","build","port-conflict"],"backgroundTag":null,"analyzedSha":"a221052e0df5b1f7598fceba7329fd1af95d6699","analyzedAt":"2026-08-16T12:47:06.542Z","schemaVersion":2},"datasetVersion":"2026-08-16T13:17:31.715Z"}