aaif-goose/goose · error
External ACP backend URL must be the base URL before /acp
Error message
External ACP backend URL must be the base URL before /acp
What it means
Thrown by normalizeAcpHttpBaseUrl when the URL path (after stripping trailing slashes) ends with '/acp'. The function's contract is to receive the base URL before the /acp segment — httpEndpointUrlFromHttpBase then appends '/status' or '/acp' itself. Users commonly paste the full ACP endpoint they see in logs (e.g. http://127.0.0.1:8080/acp), which would otherwise produce a broken /acp/acp.
Source
Thrown at ui/desktop/src/acp/url.ts:55
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}`;
return url.toString();
}
export function statusHttpUrlFromHttpBase(rawBaseUrl: string): string {
return httpEndpointUrlFromHttpBase(rawBaseUrl, 'status');
}
export function acpHttpUrlFromHttpBase(rawBaseUrl: string, token?: string): string {
const url = new URL(httpEndpointUrlFromHttpBase(rawBaseUrl, 'acp'));View on GitHub (pinned to 3810898a74)
Solutions
- Remove the trailing '/acp' segment: enter http://host:8080 or https://host/goose.
- Keep only scheme + host + port (+ base path if the backend is mounted under one).
Example fix
// before
const pathname = url.pathname.replace(/\/+$/, '');
if (pathname.endsWith('/acp')) {
throw new Error('External ACP backend URL must be the base URL before /acp');
}
// after (accept the pasted endpoint by stripping the suffix)
let pathname = url.pathname.replace(/\/+$/, '');
if (pathname.endsWith('/acp')) {
pathname = pathname.slice(0, -'/acp'.length);
} Defensive patterns
Strategy: validation
Validate before calling
// Strip an accidental /acp suffix before validating
function stripAcpSuffix(raw: string): string {
const url = new URL(raw.trim());
url.pathname = url.pathname.replace(/\/+$/, '').replace(/\/acp$/, '');
return url.toString();
} Type guard
function isBaseUrlBeforeAcp(value: string): boolean {
try {
const url = new URL(value.trim());
return !url.pathname.replace(/\/+$/, '').endsWith('/acp');
} catch {
return false;
}
} Try / catch
try {
const base = normalizeAcpHttpBaseUrl(inputUrl);
} catch (error) {
if (/before \/acp/.test(String(error))) {
return normalizeAcpHttpBaseUrl(stripAcpSuffix(inputUrl)); // user pasted the full endpoint
}
throw error;
} Prevention
- Enter scheme + host + port only; the client appends /acp and /status.
- Clarify with placeholder text: 'http://localhost:8080 (no /acp)'.
- Auto-strip the suffix at the input boundary for pasted endpoint URLs.
When it happens
Trigger: Entering 'http://host:8080/acp' or 'https://host/goose/acp/' as the external backend URL — the exact endpoint string the goose daemon prints or that getAcpUrl returns.
Common situations: Copying the WebSocket/ACP endpoint from goose serve output into the external-backend settings field; following instructions that show the full endpoint rather than the base.
Related errors
- External ACP backend URL is required
- External ACP backend URL must use http: or https:, got ${url
- External ACP backend URL must not include query parameters o
- Invalid base URL: {}
- Failed to construct URL: {}
AI-assisted analysis of aaif-goose/goose@3810898a74 (2026-08-16).
Data as JSON: /api/errors/eed310b1e2d0ecc5.
Report an issue: GitHub.