tinyhumansai/openhuman · error · Error
timed out waiting for spawned core at ${coreUrl} ${stderrFn(
Error message
timed out waiting for spawned core at ${coreUrl}
${stderrFn()} What it means
Thrown by waitForCore() in harness-cache-audit when the 120-second readiness deadline expires. The child process is still alive (exitCode is null) but every attempt to POST core.ping to coreUrl has failed, so the script gives up and prints the endpoint plus the core's stderr tail. It means the core started but never answered on the expected /rpc URL within 120s.
Source
Thrown at scripts/debug/harness-cache-audit.mjs:549
]);
}
async function waitForCore(coreUrl, token, child, stderrFn) {
const deadline = Date.now() + 120_000;
while (Date.now() < deadline) {
if (child.exitCode !== null) {
throw new Error(
`spawned core exited with ${child.exitCode}\n${stderrFn()}`,
);
}
try {
await rpc(coreUrl, token, "core.ping", {}, 10_000);
return;
} catch {
await new Promise((resolve) => setTimeout(resolve, 750));
}
}
throw new Error(
`timed out waiting for spawned core at ${coreUrl}\n${stderrFn()}`,
);
}
async function main() {
const opts = parseArgs(process.argv.slice(2));
if (!opts.workspace) opts.workspace = await defaultWorkspace();
let tempWorkspace = "";
let spawned;
if (opts.isolatedWorkspace) {
if (!opts.spawnCore)
throw new Error("--isolated-workspace requires --spawn-core");
tempWorkspace = await mkdtemp(
path.join(tmpdir(), "openhuman-harness-cache-audit-"),
);
opts.workspace = path.join(tempWorkspace, "workspace");
await mkdir(opts.workspace, { recursive: true });View on GitHub (pinned to a221052e0d)
Solutions
- Read the embedded stderr tail — a still-initializing core shows migration/store init progress; if it looks healthy, the URL/token is the problem
- If OPENHUMAN_CORE_RPC_URL is exported, unset it (or pass an explicit matching --core-url) so --spawn-core auto-picks the port it actually binds
- Verify the token the script uses matches the spawned core's token (with --spawn-core the script generates it; don't also pass --token)
- Give the core a smaller/fresher workspace (--isolated-workspace) to shorten boot
- Retry on a loaded machine — if boot genuinely needs >120s, run the core manually and attach without --spawn-core
Example fix
# before: exported stale URL overrides the spawned core's address export OPENHUMAN_CORE_RPC_URL=http://127.0.0.1:8765/rpc node scripts/debug/harness-cache-audit.mjs --spawn-core # after: let the harness pick the port for the core it spawns unset OPENHUMAN_CORE_RPC_URL node scripts/debug/harness-cache-audit.mjs --spawn-core
Defensive patterns
Strategy: retry
Validate before calling
// pre-flight the endpoint shape before entering the wait loop
import { request } from "node:http";
const pre = await fetch(coreUrl.replace(/\/rpc$/, "/health"), { signal: AbortSignal.timeout(2000) }).catch(() => null);
if (pre && pre.ok) console.log("core answering /health; /rpc readiness likely imminent"); Try / catch
for (let attempt = 1; attempt <= 2; attempt++) {
try { await runAudit(opts); break; }
catch (err) {
if (!/timed out waiting for spawned core/.test(String(err.message)) || attempt === 2) throw err;
await new Promise((r) => setTimeout(r, 5000)); // machine was loaded; retry once
}
} Prevention
- Unset OPENHUMAN_CORE_RPC_URL when using --spawn-core so the auto-picked port is authoritative
- Don't pass --token together with --spawn-core
- Keep audited workspaces small or isolated to keep boot under the 120s window
When it happens
Trigger: `--spawn-core` with a very slow boot (large workspace migration, cold model/store init taking >120s); a wrong --core-url when OPENHUMAN_CORE_RPC_URL was exported (coreUrlExplicit path skips the auto-picked port); a bearer token mismatch making ping return 401 forever (each rpc() throw is treated as not-ready); the chosen port stolen between pickFreePort() and core bind; core bound to a different interface than 127.0.0.1.
Common situations: First run against a huge existing workspace that needs a long migration; exporting OPENHUMAN_CORE_RPC_URL pointing at an old/dead port and combining it with --spawn-core; heavy CI machine where startup exceeds 2 minutes; token file from a previous core run no longer matching.
Understand the failure class
- Timeouts: ETIMEDOUT, deadlines, and hung requests — what actually expires when a request times out.
Related errors
- spawned core exited with ${child.exitCode} ${stderrFn()}
- Invalid ${paramName}: '${value}'. Must be a valid integer ID
- Core RPC token unavailable in Tauri; local RPC auth cannot b
- Core RPC ${payload.method} timed out after ${effectiveTimeou
- Core RPC HTTP ${response.status}: ${text || response.statusT
AI-assisted analysis of tinyhumansai/openhuman@a221052e0d (2026-08-16).
Data as JSON: /api/errors/2020dd7eb63027cc.
Report an issue: GitHub.