google-gemini/gemini-cli · error · OAuthSecurityError
Invalid OAuth endpoint URL "${resolvedUrl}": ${getErrorMessa
Error message
Invalid OAuth endpoint URL "${resolvedUrl}": ${getErrorMessage(e)} What it means
The resolved OAuth endpoint string is not parseable as an absolute URL. After optional relative-resolution, the library runs new URL(resolvedUrl) and throws this OAuthSecurityError if parsing fails. This means the value is not a URL at all (no scheme/host) or contains syntax the WHATWG URL parser rejects.
Source
Thrown at packages/core/src/mcp/oauth-utils.ts:81
urlStr: string,
options?: OAuthUrlValidationOptions,
): Promise<string> {
let resolvedUrl = urlStr.trim();
if (options?.allowRelative && options.baseUri) {
try {
resolvedUrl = new URL(resolvedUrl, options.baseUri).toString();
} catch (e) {
throw new OAuthSecurityError(
`Failed to resolve relative OAuth URL "${urlStr}" against base "${options.baseUri}": ${getErrorMessage(e)}`,
);
}
}
let parsed: URL;
try {
parsed = new URL(resolvedUrl);
} catch (e) {
throw new OAuthSecurityError(
`Invalid OAuth endpoint URL "${resolvedUrl}": ${getErrorMessage(e)}`,
);
}
const isHttp = parsed.protocol === 'http:';
const isHttps = parsed.protocol === 'https:';
if (!isHttp && !isHttps) {
throw new OAuthSecurityError(
`Invalid OAuth endpoint protocol "${parsed.protocol}". Only HTTPS (and HTTP for local development) is supported.`,
);
}
const hostname = sanitizeHostname(parsed.hostname);
const isLoopback = isLoopbackHost(hostname);
if (isHttp && (!options?.allowLoopback || !isLoopback)) {
throw new OAuthSecurityError(
`Insecure HTTP OAuth endpoint "${resolvedUrl}" is not allowed. OAuth endpoints must use HTTPS unless connecting to localhost.`,View on GitHub (pinned to 3c311beac2)
Solutions
- Ensure the endpoint string includes a full scheme and host, e.g. 'https://auth.example.com/oauth/authorize'
- If the value is intentionally relative, pass { allowRelative: true, baseUri: '<absolute base>' } so it gets resolved first
- Check for stray whitespace, quotes, or template-literal artifacts in the configured value (urlStr is trimmed, but embedded characters still break parsing)
- Inspect the raw authorization_server/registration_endpoint metadata your server returns and fix it server-side if it is malformed
Example fix
// before
await validateOAuthEndpointUrl('auth.example.com/oauth/authorize');
// after
await validateOAuthEndpointUrl('https://auth.example.com/oauth/authorize'); Defensive patterns
Strategy: validation
Validate before calling
function isParseableAbsoluteUrl(v: string): boolean {
try { new URL(v); return true; } catch { return false; }
}
if (!isParseableAbsoluteUrl(endpoint) && !opts?.allowRelative) {
throw new Error(`Config bug: endpoint '${endpoint}' must be an absolute URL`);
} Type guard
function isValidHttpUrl(v: unknown): v is string {
if (typeof v !== 'string') return false;
try { const u = new URL(v); return u.protocol === 'http:' || u.protocol === 'https:'; } catch { return false; }
} Try / catch
try {
await validateOAuthEndpointUrl(endpoint);
} catch (e) {
if (e instanceof OAuthSecurityError && e.message.startsWith('Invalid OAuth endpoint URL')) {
// log the raw endpoint value and its source (env/config/metadata), fix the string
}
throw e;
} Prevention
- Always configure full https:// URLs for OAuth endpoints
- Validate discovered metadata endpoint strings before use
- Add a lint/startup check that every URL-typed config value passes new URL()
When it happens
Trigger: Passing a bare hostname ('auth.example.com'), a path-only string without allowRelative/baseUri ('/oauth/authorize'), or a string with invalid URL characters to validateOAuthEndpointUrl.
Common situations: OAuth metadata discovered from a server returns malformed endpoint values; configuration typos like missing 'https://'; copying endpoint values from docs or .env files that lost the scheme or gained trailing punctuation.
Understand the failure class
Background: "Invalid URL" / "URL cannot be empty": fix the malformed or missing URL behind request-construction failures — this error's family across 50 libraries.
Related errors
- Failed to resolve relative OAuth URL "${urlStr}" against bas
- Attempted to save credentials without an access token.
- Invalid repo URL: ${source}
- Invalid GitHub repository source: ${source}. Expected "owner
- Invalid OAuth endpoint protocol "${parsed.protocol}". Only H
AI-assisted analysis of google-gemini/gemini-cli@3c311beac2 (2026-08-27).
Data as JSON: /api/errors/1635e6b829f225b7.
Report an issue: GitHub.