headroomlabs-ai/headroom · error · Error

Invalid proxyUrl: "${proxyUrl}"

Error message

Invalid proxyUrl: "${proxyUrl}"

What it means

normalizeAndValidateProxyUrl() could not parse the configured proxyUrl with the WHATWG URL constructor — the string is not a valid absolute URL at all (before any scheme/host checks happen). Typical culprits are missing scheme, stray characters, or a bare host:port.

Source

Thrown at plugins/openclaw/src/proxy-manager.ts:409

        encoding: "utf8",
        stdio: ["ignore", "pipe", "ignore"],
        timeout: 5000,
      });
      if (result.error || result.status !== 0) return null;
      const prefix = (result.stdout ?? "").trim();
      return prefix.length > 0 ? prefix : null;
    } catch {
      return null;
    }
  }
}

/** Parse a URL, returning the parsed object or throwing a descriptive error. */
function parseProxyUrl(proxyUrl: string): URL {
  try {
    return new URL(proxyUrl);
  } catch {
    throw new Error(`Invalid proxyUrl: "${proxyUrl}"`);
  }
}

export function normalizeAndValidateProxyUrl(proxyUrl: string): string {
  const parsed = parseProxyUrl(proxyUrl);

  if (parsed.protocol !== "http:" && parsed.protocol !== "https:") {
    throw new Error("proxyUrl must use http:// or https://");
  }

  if (parsed.pathname !== "/" || parsed.search || parsed.hash) {
    throw new Error("proxyUrl must not include a path, query, or hash");
  }

  return parsed.origin;
}

/** Returns true if the URL points to a local address (localhost or 127.0.0.1). */

View on GitHub (pinned to 322425c43b)

Solutions

  1. Include the scheme: use "http://127.0.0.1:8787" not "127.0.0.1:8787"
  2. Trim whitespace/newlines when the URL comes from env vars or config files
  3. Sanity-check the value in a REPL: new URL(value) must not throw before passing it in

Example fix

// before
manager.configure({ proxyUrl: "localhost:8787" }); // throws

// after
manager.configure({ proxyUrl: "http://localhost:8787" });
Defensive patterns

Strategy: type-guard

Validate before calling

function isParseableUrl(value: string): boolean {
  try {
    new URL(value);
    return true;
  } catch {
    return false;
  }
}

if (!isParseableUrl(proxyUrl)) {
  throw new Error(`proxyUrl '${proxyUrl}' is not a valid absolute URL — include the scheme, e.g. http://...`);

Type guard

function isValidAbsoluteUrl(value: string): value is `http://${string}` | `https://${string}` {
  try {
    const u = new URL(value);
    return u.protocol === "http:" || u.protocol === "https:";
  } catch {
    return false;
  }
}

Prevention

When it happens

Trigger: Passing proxyUrl values like "localhost:8787" (interpreted as scheme, actually invalid here), "127.0.0.1:8787", "headroom proxy", or a string with whitespace/control characters to normalizeAndValidateProxyUrl().

Common situations: Bare host:port copied from CLI docs; trailing newline from an env var or config file; URL assembled by string concatenation with a typo; scheme accidentally deleted during editing.

Related errors


AI-assisted analysis of headroomlabs-ai/headroom@322425c43b (2026-08-15). Data as JSON: /api/errors/e3504effbe17137c. Report an issue: GitHub.