aaif-goose/goose · error
External ACP backend URL is required
Error message
External ACP backend URL is required
What it means
Thrown by normalizeAcpHttpBaseUrl when the external ACP backend URL, after trimming, is an empty string. The function is the single entry point for turning a user-supplied base URL (external-backend mode) into status/acp endpoint URLs, and it validates stepwise: presence, scheme, query/fragment, path suffix. This first guard means no URL was provided at all.
Source
Thrown at ui/desktop/src/acp/url.ts:41
}
const hostname = url.hostname.toLowerCase().replace(/^\[(.*)\]$/, '$1');
return hostname === 'localhost' || hostname === '::1' || isIpv4LoopbackLiteral(hostname);
}
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}`;
}View on GitHub (pinned to 3810898a74)
Solutions
- Provide the base URL of the running goose backend, e.g. http://127.0.0.1:8080 (no /acp suffix).
- If using an env var, confirm it is set in the environment the Electron process actually inherits (not just your shell).
- Validate the settings field before entering external mode so the user is prompted instead of hitting this throw.
Example fix
// before
const trimmed = rawBaseUrl.trim();
if (!trimmed) {
throw new Error('External ACP backend URL is required');
}
// after (caller-side gate with a friendly message)
function requireExternalAcpUrl(url: string | undefined | null): string {
const value = (url ?? '').trim();
if (!value) throw new Error('External ACP backend URL is required');
return normalizeAcpHttpBaseUrl(value);
} Defensive patterns
Strategy: validation
Validate before calling
// Gate external mode on a non-empty URL before any ACP call
function externalAcpBaseUrlOrNull(settings: { url?: string | null }): string | null {
const value = (settings.url ?? '').trim();
return value.length > 0 ? value : null;
} Type guard
function isNonEmptyUrl(value: string | null | undefined): value is string {
return typeof value === 'string' && value.trim().length > 0;
} Try / catch
try {
const base = normalizeAcpHttpBaseUrl(inputUrl);
} catch (error) {
if (/is required/.test(String(error))) {
setFieldError('backendUrl', 'Enter the goose backend base URL, e.g. http://127.0.0.1:8080');
return;
}
throw error;
} Prevention
- Make the URL field required in the UI when external-backend mode is toggled on.
- Persist a validated URL so subsequent launches never pass an empty string.
- Trim input before saving settings.
When it happens
Trigger: Calling normalizeAcpHttpBaseUrl('') or ' ' directly; external-backend mode enabled in the desktop app but the URL setting/env var never populated; a settings field read from an unset key (undefined coerced or defaulted to '').
Common situations: Enabling 'use external goose backend' without filling the URL input; env var (e.g. GOOSE_DESKTOP_EXTERNAL_ACP_URL) not exported in the shell that launched the app; fresh profile where the setting is unset.
Related errors
- External ACP backend URL must use http: or https:, got ${url
- 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/3236c07ed37f4cad.
Report an issue: GitHub.