can1357/oh-my-pi · error
Timed out waiting ${timeoutSec} seconds for Vibemon VM ${san
Error message
Timed out waiting ${timeoutSec} seconds for Vibemon VM ${sandbox.id} to become ready What it means
waitUntilRunning polls the sandbox state every 250ms until timeoutSec elapses. If the sandbox never reports running (and never enters a terminal state) within that window, this timeout error is thrown naming the sandbox id and the configured timeout.
Source
Thrown at packages/metaharness/src/tb/vmon.ts:70
if (!client) {
client = connect(config.url, { token: config.token || undefined });
clients.set(key, client);
}
return client;
}
async function waitUntilRunning(sandbox: Sandbox, timeoutSec: number): Promise<void> {
const deadline = Date.now() + timeoutSec * 1_000;
while (Date.now() < deadline) {
const info = await sandbox.refresh();
const state = String(info.observed_state ?? info.status ?? "").toLowerCase();
if (state === "running") return;
if (["exited", "failed", "stopped", "terminated"].includes(state)) {
throw new Error(`Vibemon VM ${sandbox.id} entered ${state} before becoming ready`);
}
await Bun.sleep(250);
}
throw new Error(`Timed out waiting ${timeoutSec} seconds for Vibemon VM ${sandbox.id} to become ready`);
}
async function archiveDirectory(root: string): Promise<Blob> {
const entries: Record<string, Uint8Array> = {};
const visit = async (dir: string): Promise<void> => {
for (const entry of await fs.readdir(dir, { withFileTypes: true })) {
const absolute = path.join(dir, entry.name);
if (entry.isDirectory()) {
await visit(absolute);
} else if (entry.isFile()) {
const relative = path.relative(root, absolute).split(path.sep).join("/");
entries[relative] = new Uint8Array(await Bun.file(absolute).arrayBuffer());
}
}
};
await visit(root);
return new Bun.Archive(entries, { compress: "gzip", level: 6 }).blob();
}View on GitHub (pinned to 9690622007)
Solutions
- Increase the timeoutSec passed to start() to accommodate slow image pulls or hosts
- Check the sandbox status endpoint/API for the sandbox id to see the stuck state
- Pre-pull or pre-warm the VM image to remove cold-start latency
- Retry the start; if the state is permanently stuck, terminate and recreate the sandbox
Example fix
// before
await vm.start({ timeoutSec: 30 });
// after
await vm.start({ timeoutSec: 300 }); Defensive patterns
Strategy: retry
Try / catch
try {
await vm.start();
} catch (err) {
if (/Timed out waiting \d+ seconds for Vibemon VM/.test(err.message)) {
await terminateSandbox(vm.id); // clean up the stuck sandbox
const fresh = await createSandbox(config); // retry with a fresh instance
await fresh.start({ timeoutSec: 300 });
return fresh;
}
throw err;
} Prevention
- Set timeoutSec generously (image pulls and cold hosts are slow)
- Pre-warm/pre-pull VM images before batch runs
- Always terminate sandboxes after a timeout so orphaned VMs don't accumulate
When it happens
Trigger: Calling start() when the VM boots too slowly (image pull, slow host), or its state endpoint keeps reporting a non-running, non-terminal state (e.g. 'provisioning', 'pending') for longer than timeoutSec.
Common situations: Large VM image downloads on cold caches; overloaded host delaying startup; upstream API stuck reporting 'creating'; timeoutSec set too low for the environment.
Understand the failure class
- Timeouts: ETIMEDOUT, deadlines, and hung requests — what actually expires when a request times out.
Related errors
- Socket not ready after ${timeoutMs}ms
- Vibemon VM ${sandbox.id} entered ${state} before becoming re
- Timed out waiting for RPC ready signal. Stderr: {stderr}
- timed out: {command}
- Unable to read OMP_AUTH_BROKER_ACCOUNT_POOL_FILE at ${filePa
AI-assisted analysis of can1357/oh-my-pi@9690622007 (2026-08-31).
Data as JSON: /api/errors/57625236d3585853.
Report an issue: GitHub.