Hmbown/CodeWhale · warning · Error
The check was interrupted. You can run it again when ready.
Error message
The check was interrupted. You can run it again when ready.
What it means
The until() helper spins waiting for a condition (app ready, apply event, new samples). If the spawned practice process exits (child.exitCode !== null) or the 15-second AbortController fires while the condition is still unmet, until() throws this error instead of hanging. It means the check was cut short, not that the checked behavior failed.
Solutions
- Simply retry runBackgroundCheck() — the message is explicitly designed as a re-runnable interruption.
- Check whether the practice app binary launches cleanly outside the check to rule out crashes.
- If timeouts are frequent on your hardware, allow more wall time or investigate what slows the app's 'ready' event.
Example fix
// before
await runBackgroundCheck({ bundle }); // may throw on transient interruption
// after
try {
await runBackgroundCheck({ bundle });
} catch (e) {
if (String(e.message).includes("interrupted")) {
await runBackgroundCheck({ bundle }); // one clean retry
} else throw e;
} Defensive patterns
Strategy: retry
Try / catch
const MAX_ATTEMPTS = 3;
for (let attempt = 1; attempt <= MAX_ATTEMPTS; attempt++) {
try {
return await runBackgroundCheck({ bundle });
} catch (e) {
const interrupted = String(e.message).includes("interrupted");
if (!interrupted || attempt === MAX_ATTEMPTS) throw e;
await new Promise(r => setTimeout(r, 1000 * attempt));
}
} Prevention
- Run the check on a quiet machine; background load makes the 15s window tight.
- Retry once automatically on this specific message before surfacing to the user.
- Confirm the practice binary launches standalone if interruptions repeat.
When it happens
Trigger: Inside runBackgroundCheck, any await until(...) where the practice child process crashes/exits early, or the 15s timer aborts controller.signal before the predicate becomes true.
Common situations: Slow machines where the app takes longer than 15s to become ready, the practice binary crashing at startup, or the abort timeout firing during a long typing/screenshot step.
Related errors
- child wall-time budget exhausted; continuation cannot reset…
- child wall-time budget exhausted
- child wall-time budget exhausted
- clipboard read failed
- cloud agent created but its labels could not be applied
AI-assisted analysis of Hmbown/CodeWhale@73e0f67d83 (2026-09-22).
Data as JSON: /api/errors/00a7f3f5c6deb34d.
Report an issue: GitHub.
Appendix: source
Thrown at crates/tui/plugins/computer-use/app/background-check.mjs:35
const child = spawn(executable, [], { stdio: ["ignore", "pipe", "pipe"] });
const scratch = fs.mkdtempSync(path.join(os.tmpdir(), "cu-setup-capture-"));
let ready = false, applied = null, latest = null, buffer = "", spawnError = null;
child.on("error", error => { spawnError = error; });
child.stderr.on("data", () => {});
child.stdout.setEncoding("utf8");
child.stdout.on("data", chunk => {
buffer += chunk;
if (buffer.length > 16_384) { controller.abort(); return; }
let newline;
while ((newline = buffer.indexOf("\n")) >= 0) {
const line = buffer.slice(0, newline); buffer = buffer.slice(newline + 1);
try { const result = JSON.parse(line); latest = result; if (result.event === "ready") ready = true; if (result.event === "applied") applied = result; } catch { /* Cocoa diagnostics are not receipts. */ }
}
});
async function until(predicate) {
while (!predicate()) {
if (spawnError) throw spawnError;
if (controller.signal.aborted || child.exitCode !== null) throw new Error("The check was interrupted. You can run it again when ready.");
await delay(40);
}
}
async function call(tool, args = {}) {
const reply = await handle({ tool, args }, { sessionId, signal: controller.signal, persistentInputOwner: true });
if (!reply.ok) throw new Error(reply.error.message);
return reply.data;
}
try {
await until(() => ready);
await call("open_application", { pid: child.pid, activate: false });
const state = await call("get_app_state");
if (demoDirectory) {
fs.mkdirSync(demoDirectory, { recursive: true });
// AX can register before WindowServer makes a new window capturable.
// Retry only this read, before sending any input, within the check limit.
while (true) {
try { await call("screenshot", { app_ref: { pid: child.pid }, path: path.join(demoDirectory, "01-ready.png") }); break; }View on GitHub (pinned to 73e0f67d83)