Hmbown/CodeWhale · error · ExecError

open failed

Error message

open failed: ${r.stderr.trim().slice(0, 200)}

What it means

The macOS `open` command (run with a 25s timeout to launch the app by -a name or -b bundle_id, optionally a URL and -g for background) exited non-zero. The first 200 characters of its stderr are embedded in the message and the full result is attached to the ExecError.

Solutions

  1. Read the embedded stderr (and the attached result object) for the precise `open` failure reason.
  2. Verify the app exists: call list_apps, or check /Applications for the name/bundle id.
  3. Use the exact bundle_id (via osascript or list_apps) instead of a display name when names are ambiguous.
  4. If opening a URL, confirm a handler app is registered for its scheme.

Example fix

// before
await backend.open_application({ name: "FireFox" });
// after
await backend.open_application({ bundle_id: "org.mozilla.firefox" });
Defensive patterns

Strategy: try-catch

Validate before calling

const apps = await backend.list_apps();
if (!apps.some(a => a.name === appName || a.bundle_id === bundleId)) {
  throw new Error(`app ${appName || bundleId} not installed/running`);
}

Try / catch

try {
  await backend.open_application({ name });
} catch (e) {
  if (String(e.message).startsWith('open failed:')) {
    console.error('`open` stderr:', e.message.slice('open failed:'.length));
  } else throw e;
}

Prevention

When it happens

Trigger: open_application falls back to `open` when app_info found no matching running app; `open` fails because the app name is misspelled, the bundle id does not exist, the app is not installed, or the URL scheme is not handled.

Common situations: Typos in app names ('FireFox' vs 'Firefox'); referring to an app not installed on the machine; bundle id copied from a different platform; opening a URL whose scheme has no registered handler; Spotlight indexing issues making -a lookups fail.

Related errors


AI-assisted analysis of Hmbown/CodeWhale@433685b202 (2026-09-15). Data as JSON: /api/errors/8386983f6a850105. Report an issue: GitHub.

Appendix: source

Thrown at crates/tui/plugins/computer-use/src/backends/darwin.mjs:570

    const find = {};
    if (pid) find.pid = pid; else if (bid) find.bundle_id = bid; else find.name = String(name).replace(/\.app$/, "");
    let p;
    // Binding an already-running app must not ask LaunchServices to reopen
    // it: reopen can raise windows even with open -g on some applications.
    if (!urlArg) {
      try { p = await native("app_info", { app_ref: find, activate }); }
      catch (error) {
        if (!error.message.includes("application not found")) throw error;
      }
    }
    if (!p?.found) {
      if (!name && !bid) throw new ExecError(`no running application with pid ${pid}; call list_apps for the current processes`);
      const args = [];
      if (urlArg) args.push(urlArg);
      if (bid) args.unshift("-b", bid); else args.unshift("-a", name);
      if (!activate) args.unshift("-g");
      const r = await runL("open", args, { timeoutMs: 25_000 });
      if (r.code !== 0) throw new ExecError(`open failed: ${r.stderr.trim().slice(0, 200)}`, r);
      await new Promise((res) => setTimeout(res, 600));
      p = await native("app_info", { app_ref: find, activate });
    }
    if (activate && p?.frontmost === false) throw Object.assign(new ExecError("The selected application did not become frontmost; no input mode was enabled. Continue with background control or wait for the user."), { code: "activation_not_confirmed" });
    if (p?.bundle_id === "net.codewhale.computer-use") throw Object.assign(new ExecError("The Computer Use setup and safety controls belong to the user and cannot be operated by this plugin."), { code: "protected_application" });
    // A bare executable has no bundle id; carrying an empty one would make the
    // identity unmatchable.
    state.inputApp = { pid: p.pid, ...(p.bundle_id ? { bundle_id: p.bundle_id } : {}) };
    state.foregroundInput = !!activate;
    return { launched: true, activate, keyboard_delivery: activate ? "foreground-guarded" : "process", input_scope: activate ? "shared-desktop" : "application", shared_pointer: !!activate, isolated_desktop: false, url: urlArg ?? null, resolved: p?.found ? { name: p.name, pid: p.pid, bundle_id: p.bundle_id, frontmost: p.frontmost } : null };
  }

  // ---------- clipboard / cursor / waits ----------
  async function readClipboard() {
    const r = await runL("pbpaste", [], { timeoutMs: 5_000, maxBuffer: 4 * 1024 * 1024 });
    return { text: r.stdout, encoding: "utf8" };
  }
  async function writeClipboard({ text }) {

View on GitHub (pinned to 433685b202)