aaif-goose/goose · error
External ACP backend URL must use http: or https:, got ${url
Error message
External ACP backend URL must use http: or https:, got ${url.protocol} What it means
Thrown by normalizeAcpHttpBaseUrl when the input parses as a URL but its protocol is neither http: nor https:. Because the endpoint is used to build WebSocket/HTTP ACP endpoints, the code requires a plain web scheme and rejects anything else — most commonly ws:// or wss:// pasted by users who copied the WebSocket URL, or file:///ftp:// typos.
Source
Thrown at ui/desktop/src/acp/url.ts:46
function isIpv4LoopbackLiteral(hostname: string): boolean {
const octets = hostname.split('.');
if (octets.length !== 4 || octets.some((octet) => !/^\d+$/.test(octet))) {
return false;
}
return octets.every((octet) => Number(octet) <= 255) && Number(octets[0]) === 127;
}
export function normalizeAcpHttpBaseUrl(rawBaseUrl: string): string {
const trimmed = rawBaseUrl.trim();
if (!trimmed) {
throw new Error('External ACP backend URL is required');
}
const url = new URL(trimmed);
if (url.protocol !== 'http:' && url.protocol !== 'https:') {
throw new Error(`External ACP backend URL must use http: or https:, got ${url.protocol}`);
}
if (url.search || url.hash) {
throw new Error('External ACP backend URL must not include query parameters or fragments');
}
const pathname = url.pathname.replace(/\/+$/, '');
if (pathname.endsWith('/acp')) {
throw new Error('External ACP backend URL must be the base URL before /acp');
}
return `${url.origin}${pathname}`;
}
function httpEndpointUrlFromHttpBase(rawBaseUrl: string, endpoint: 'status' | 'acp'): string {
const baseUrl = normalizeAcpHttpBaseUrl(rawBaseUrl);
const url = new URL(baseUrl);
url.pathname = `${url.pathname.replace(/\/+$/, '')}/${endpoint}`;View on GitHub (pinned to 3810898a74)
Solutions
- Use the http(s) base URL of the backend (e.g. http://127.0.0.1:8080) — the code appends /acp itself.
- If the value starts with ws:// or wss://, convert the scheme to http:// or https:// and keep host/port.
- Always include the scheme; host:port alone makes new URL throw a different error.
Example fix
// before
const url = new URL(trimmed);
if (url.protocol !== 'http:' && url.protocol !== 'https:') {
throw new Error(`External ACP backend URL must use http: or https:, got ${url.protocol}`);
}
// after (auto-correct the common ws paste, then validate)
const corrected = trimmed.replace(/^wss?:\/\//i, (m) => (m.toLowerCase() === 'ws://' ? 'http://' : 'https://'));
const url = new URL(corrected);
if (url.protocol !== 'http:' && url.protocol !== 'https:') {
throw new Error(`External ACP backend URL must use http: or https:, got ${url.protocol}`);
} Defensive patterns
Strategy: validation
Validate before calling
// Normalize the common ws:// paste, then check the scheme
function toHttpBaseUrl(raw: string): string {
const value = raw.trim().replace(/^ws:\/\//i, 'http://').replace(/^wss:\/\//i, 'https://');
const { protocol } = new URL(value);
if (protocol !== 'https:' && protocol !== 'http:') {
throw new Error(`Unsupported scheme ${protocol}; use http:// or https://`);
}
return value;
} Type guard
function isHttpUrl(value: string): boolean {
try {
const { protocol } = new URL(value.trim());
return protocol === 'http:' || protocol === 'https:';
} catch {
return false;
}
} Try / catch
try {
const base = normalizeAcpHttpBaseUrl(inputUrl);
} catch (error) {
if (/must use http: or https:/.test(String(error))) {
setFieldError('backendUrl', 'Use http:// or https:// — the /acp websocket path is added automatically');
return;
}
throw error;
} Prevention
- Paste the plain http(s) origin of the backend, never a ws:// endpoint.
- Validate with isHttpUrl on input change to give inline feedback.
- Document 'base URL' in the field's placeholder text.
When it happens
Trigger: normalizeAcpHttpBaseUrl('ws://127.0.0.1:8080/acp') — user copied the ws URL from logs; 'unix:///path' or 'file://...' entries; a URL missing the scheme entirely can also fail URL parsing (that throws a TypeError from new URL, not this message).
Common situations: Copy-pasting the ws:// URL that getAcpUrl returns elsewhere in the app; docs or tutorials showing the WebSocket endpoint; automation writing scheme-less host:port values.
Related errors
- External ACP backend URL is required
- External ACP backend URL must not include query parameters o
- External ACP backend URL must be the base URL before /acp
- Invalid base URL: {}
- Failed to construct URL: {}
AI-assisted analysis of aaif-goose/goose@3810898a74 (2026-08-16).
Data as JSON: /api/errors/aa5f7edc7e962dc0.
Report an issue: GitHub.