can1357/oh-my-pi · error
Vibemon VM ${sandbox.id} entered ${state} before becoming re
Error message
Vibemon VM ${sandbox.id} entered ${state} before becoming ready What it means
waitUntilRunning polls the Vibemon sandbox's observed state until it reports running. If the sandbox instead reports a terminal state (exited, failed, stopped, or terminated) before ever becoming ready, this error is thrown immediately with the VM id and the observed state, rather than waiting out the whole timeout.
Source
Thrown at packages/metaharness/src/tb/vmon.ts:66
function clientFor(config: VmonConfig): Client {
const key = `${config.url}\0${config.token}`;
let client = clients.get(key);
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());
}
}View on GitHub (pinned to 9690622007)
Solutions
- Inspect VM/container logs for the sandbox id reported in the message to find the boot failure
- Validate the VM image boots standalone (run it locally with the same entrypoint)
- Increase host memory/CPU or reduce concurrent sandboxes to avoid OOM/preemption
- Check for other processes or cleanup jobs stopping the sandbox during startup
Example fix
// before: crashed image
new Vibemon({ image: "my-vm:broken" })
// after: validated image that reaches running state
new Vibemon({ image: "my-vm:fixed", resources: { memoryMB: 4096 } }) Defensive patterns
Strategy: retry
Try / catch
try {
await vm.start();
} catch (err) {
if (/entered (exited|failed|stopped|terminated) before becoming ready/.test(err.message)) {
const logs = await fetchSandboxLogs(vm.id);
logger.error("VM boot failed", { id: vm.id, logs });
throw err; // boot failure is usually not transient; surface with logs
}
throw err;
} Prevention
- Validate VM images boot standalone before registering them for trials
- Right-size host memory/CPU to avoid OOM kills during parallel starts
- Avoid concurrent lifecycle operations (stop/terminate) on the same sandbox id
When it happens
Trigger: Calling start() on a Vibemon VM whose container/VM exits, fails, stops, or is terminated during the readiness poll window — e.g. image crash on boot, bad entrypoint, OOM kill, or externally issued stop.
Common situations: Broken VM image that crashes at startup; insufficient host resources causing OOM; orchestrator preempting the sandbox; concurrent run killing the sandbox by name.
Related errors
- Timed out waiting ${timeoutSec} seconds for Vibemon VM ${san
- Unable to read OMP_AUTH_BROKER_ACCOUNT_POOL_FILE at ${filePa
- xAI device-code token polling failed: ${error instanceof Err
- blob broker exposure failed to start
- Cannot change working directory to ${parsed.cwd}: ${reason}.
AI-assisted analysis of can1357/oh-my-pi@9690622007 (2026-08-31).
Data as JSON: /api/errors/f3dafaefc86e72b5.
Report an issue: GitHub.