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

  1. Ensure the endpoint string includes a full scheme and host, e.g. 'https://auth.example.com/oauth/authorize'
  2. If the value is intentionally relative, pass { allowRelative: true, baseUri: '<absolute base>' } so it gets resolved first
  3. Check for stray whitespace, quotes, or template-literal artifacts in the configured value (urlStr is trimmed, but embedded characters still break parsing)
  4. 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

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


AI-assisted analysis of google-gemini/gemini-cli@3c311beac2 (2026-08-27). Data as JSON: /api/errors/1635e6b829f225b7. Report an issue: GitHub.