Hmbown/CodeWhale · error · ExecError

bad_args

bad_args

Error message

browser navigate/start need a url (http:// or https:// or about:blank)

What it means

checkBrowserUrl validates the url argument for browser navigate/start. An empty string, whitespace-only value, or non-string (undefined/null) fails the first guard and throws badArgs demanding a URL. The plugin only allows http://, https://, and about:blank targets.

Solutions

  1. Provide a url argument with a valid http:// or https:// URL, or the literal about:blank.
  2. If the target is a local file, serve it over http (e.g. a local dev server) instead of file://.
  3. Trim user/config input before passing; an all-whitespace value is treated as missing.
  4. Validate the field exists before dispatching the browser action.

Example fix

// before
await browser({ action: "navigate", url: "" });
// after
await browser({ action: "navigate", url: "https://example.com" });
Defensive patterns

Strategy: validation

Validate before calling

if (typeof url !== "string" || !url.trim()) throw new Error("navigate/start require a non-empty url");

Type guard

const hasUrl = (a) => typeof a?.url === "string" && a.url.trim().length > 0;

Try / catch

try { await browser(action) } catch (e) { if (String(e.message).includes("need a url")) { throw new Error(`caller bug: missing url for ${action.action}`); } throw e; }

Prevention

When it happens

Trigger: Calling browser navigate or browser start without a url argument, with url: "", or with a whitespace-only url.

Common situations: An LLM omitting the url field; a form/config value that is empty; constructing the action object dynamically and leaving url undefined; forgetting that file:// and chrome:// are also rejected here (different message) but empty input hits this one.

Understand the failure class

Background: "missing required argument" and "the following required arguments were not provided": what required-argument errors mean and how to fix them — this error's family across 20 libraries.

Related errors


AI-assisted analysis of Hmbown/CodeWhale@73e0f67d83 (2026-09-22). Data as JSON: /api/errors/bb4dce92bc70cf29. Report an issue: GitHub.

Appendix: source

Thrown at crates/tui/plugins/computer-use/src/browser-cdp.mjs:36

import path from "node:path";
import crypto from "node:crypto";
import { spawn } from "node:child_process";
import { ExecError, currentSignal } from "./exec.mjs";
import { stateDir } from "./registry.mjs";

const APPLICATIONS = ["Google Chrome", "Chromium", "Brave Browser", "Microsoft Edge"];
const LINUX_BINARIES = ["google-chrome", "chromium", "chromium-browser", "brave-browser", "microsoft-edge"];

const sleep = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
const badArgs = (message) => Object.assign(new ExecError(message), { code: "bad_args" });

function defaultRecordingsDir() {
  return process.env.CODEWHALE_CU_RECORDINGS_DIR || path.join(stateDir(), "recordings");
}

/** Only http(s) and about:blank can be navigated to; everything else is refused. */
export function checkBrowserUrl(url) {
  if (typeof url !== "string" || !url.trim()) throw badArgs("browser navigate/start need a url (http:// or https:// or about:blank)");
  const trimmed = url.trim();
  if (/^about:blank$/i.test(trimmed)) return trimmed;
  let parsed;
  try { parsed = new URL(trimmed); } catch { throw badArgs(`"${trimmed}" is not a URL`); }
  if (parsed.protocol !== "http:" && parsed.protocol !== "https:") {
    throw badArgs(`only http(s):// and about:blank URLs can be opened (got "${parsed.protocol}//")`);
  }
  return parsed.href;
}

/** Locate a Chromium-family browser app or binary; CODEWHALE_CU_BROWSER_APP overrides. */
export function findBrowserApp(platform = process.platform, env = process.env, exists = fs.existsSync) {
  if (env.CODEWHALE_CU_BROWSER_APP) return env.CODEWHALE_CU_BROWSER_APP;
  if (platform === "darwin") {
    for (const name of APPLICATIONS) {
      for (const root of ["/Applications", path.join(os.homedir(), "Applications")]) {
        const candidate = path.posix.join(root, `${name}.app`);
        if (exists(candidate)) return candidate;

View on GitHub (pinned to 73e0f67d83)