headroomlabs-ai/headroom · error · Error
proxyUrl must use http:// or https://
Error message
proxyUrl must use http:// or https://
What it means
The proxyUrl parsed successfully but its scheme is neither http: nor https: — Headroom routing only works over plain HTTP(S) proxies, so schemes like ws://, tcp:, or unix: are rejected upfront. This fires after parseProxyUrl succeeds but before path/query checks.
Source
Thrown at plugins/openclaw/src/proxy-manager.ts:417
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). */
export function isLocalProxyUrl(proxyUrl: string): boolean {
try {
const parsed = new URL(proxyUrl);
return parsed.hostname === "127.0.0.1" || parsed.hostname === "localhost";
} catch {
return false;
}
}View on GitHub (pinned to 322425c43b)
Solutions
- Use the proxy's HTTP(S) endpoint, e.g. "http://127.0.0.1:8787"
- If the deployment fronts Headroom with TLS, use https:// with the public origin
- Check the config template/env var that supplied the scheme (ws:// vs http:// mixups are the most common)
Example fix
// before
manager.configure({ proxyUrl: "ws://127.0.0.1:8787" }); // throws
// after
manager.configure({ proxyUrl: "http://127.0.0.1:8787" }); Defensive patterns
Strategy: type-guard
Validate before calling
function usesHttpScheme(value: string): boolean {
try {
return ["http:", "https:"].includes(new URL(value).protocol);
} catch {
return false;
}
}
if (!usesHttpScheme(proxyUrl)) {
throw new Error(`proxyUrl must use http:// or https:// (got ${proxyUrl})`); Type guard
function isHttpProxyUrl(value: string): value is string {
try {
return new URL(value).protocol === "http:" || new URL(value).protocol === "https:";
} catch {
return false;
}
} Prevention
- Never reuse ws:// or grpc:// endpoint URLs as proxyUrl — the Headroom proxy is HTTP(S) only
- Centralize the scheme choice in one config key to avoid template-level ws/http mixups
- Validate proxyUrl with the library's own normalizeAndValidateProxyUrl() during startup
When it happens
Trigger: Passing proxyUrl values such as "ws://127.0.0.1:8787", "socks5://localhost:8787", "tcp://10.0.0.1:8787", or "file:///..." to normalizeAndValidateProxyUrl().
Common situations: Reusing a WebSocket endpoint URL from other Headroom/OpenClaw tooling as proxyUrl; confusion between the proxy's HTTP port and its WS/gRPC port; template variable that injects the wrong scheme.
Related errors
- Invalid proxyUrl: "${proxyUrl}"
- proxyUrl must not include a path, query, or hash
- proxyPort must be an integer between 1 and 65535
- Invalid {TOOL_INJECTION_STICKY_ENV}={normalized!r}; expected
- unsupported headroom-bench proxy mode: {raw_mode!r}
AI-assisted analysis of headroomlabs-ai/headroom@322425c43b (2026-08-15).
Data as JSON: /api/errors/807caaddf03f3a1b.
Report an issue: GitHub.