Hmbown/CodeWhale · error · Error
Update the Computer Use app to run the background check.
Error message
Update the Computer Use app to run the background check.
What it means
After confirming a bundle path was given, runBackgroundCheck looks for the practice binary at <bundle>/Contents/Resources/Practice.app/Contents/MacOS/practice. If that file does not exist, the bundle is present but outdated or incomplete, so the check cannot launch the practice app. The message tells you to update the Computer Use app.
Solutions
- Update the Computer Use macOS app to the latest version so the bundled Practice.app exists.
- Verify the path exists before calling: fs.existsSync(path.join(bundle, 'Contents', 'Resources', 'Practice.app', 'Contents', 'MacOS', 'practice')).
- Confirm the bundle path points at the real Computer Use app, not another .app or a symlink to a stale copy.
Example fix
// before
await runBackgroundCheck({ bundle: "/Applications/Computer Use.app" }); // old install
// after
import fs from "node:fs";
import path from "node:path";
const exe = path.join(bundle, "Contents", "Resources", "Practice.app", "Contents", "MacOS", "practice");
if (!fs.existsSync(exe)) {
console.error("Practice app missing — update Computer Use first.");
} else {
await runBackgroundCheck({ bundle });
} Defensive patterns
Strategy: validation
Validate before calling
import fs from "node:fs";
import path from "node:path";
const exe = path.join(bundle, "Contents", "Resources", "Practice.app", "Contents", "MacOS", "practice");
if (!fs.existsSync(exe)) throw new Error("Practice app missing — update the Computer Use app first."); Try / catch
try {
await runBackgroundCheck({ bundle });
} catch (e) {
if (String(e.message).includes("Update the Computer Use app")) {
console.error("Install the latest Computer Use app, then retry.");
}
throw e;
} Prevention
- Keep the Computer Use app updated; the Practice.app binary only exists in recent versions.
- Proactively probe for the practice executable before running any background-check flow.
- Pin/verify the app version in setup scripts so stale installs are caught early.
When it happens
Trigger: Calling runBackgroundCheck({ bundle }) on macOS where fs.existsSync(<bundle>/Contents/Resources/Practice.app/Contents/MacOS/practice) is false — an old app version bundled before Practice.app was added, or a wrong/custom bundle path.
Common situations: Users running an older installed version of the Computer Use app that predates the background-check feature, or pointing bundle at a different .app (e.g. a stub or wrong install).
Understand the failure class
Background: "File not found" and ENOENT errors: why libraries can't find a file that should exist — this error's family across 50 libraries.
Related errors
- The downloaded app has a different version.
- application not found — call list_apps for exact names/pids
- background preview capture failed
- choose one available display for recording
- Codewhale-owned OAuth credentials were not found at
AI-assisted analysis of Hmbown/CodeWhale@73e0f67d83 (2026-09-22).
Data as JSON: /api/errors/33238b13bdc06da2.
Report an issue: GitHub.
Appendix: source
Thrown at crates/tui/plugins/computer-use/app/background-check.mjs:13
import fs from "node:fs";
import path from "node:path";
import os from "node:os";
import crypto from "node:crypto";
import { spawn } from "node:child_process";
import { setTimeout as delay } from "node:timers/promises";
import { handle, closeSession } from "../src/app-handler.mjs";
/** Uses the same daemon backend and cancellation path as connected hosts. */
export async function runBackgroundCheck({ bundle, demoDirectory } = {}) {
if (process.platform !== "darwin" || !bundle) throw new Error("The background check requires the installed macOS app.");
const executable = path.join(bundle, "Contents", "Resources", "Practice.app", "Contents", "MacOS", "practice");
if (!fs.existsSync(executable)) throw new Error("Update the Computer Use app to run the background check.");
const sessionId = `setup-${crypto.randomUUID()}`;
const controller = new AbortController();
const timer = setTimeout(() => controller.abort(), 15_000);
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. */ }
}
});View on GitHub (pinned to 73e0f67d83)