can1357/oh-my-pi · error

Invalid OAuth URLs. Please check: Authorization URL: ${aut

Error message

Invalid OAuth URLs. Please check:
  Authorization URL: ${authUrl}
  Token URL: ${tokenUrl}

What it means

When configuring OAuth for an MCP server via the mcp command, the provided authorization URL and token URL are parsed with the URL constructor. If either fails to parse (malformed scheme, missing host, typos, whitespace garbage), this error is thrown listing both URLs so the user can see which value is bad.

Source

Thrown at packages/coding-agent/src/modes/controllers/mcp-command-controller.ts:858

			/**
			 * External cancellation source: when this signal aborts, the in-flight
			 * OAuth flow is torn down and {@link MCPOAuthCancelledError} is thrown.
			 * Wizards (which own focus and absorb Esc themselves) pass their own
			 * controller here; editor-focused callers rely on the Esc hook
			 * installed below instead.
			 */
			abortSignal?: AbortSignal;
		},
	): Promise<OAuthFlowResult> {
		const authStorage = this.ctx.session.modelRegistry.authStorage;
		let parsedAuthUrl: URL;

		// Validate OAuth URLs
		try {
			parsedAuthUrl = new URL(authUrl);
			new URL(tokenUrl);
		} catch (_error) {
			throw new Error(
				`Invalid OAuth URLs. Please check:\n  Authorization URL: ${authUrl}\n  Token URL: ${tokenUrl}`,
			);
		}

		const resolvedClientId = clientId.trim() || parsedAuthUrl.searchParams.get("client_id")?.trim() || undefined;
		const resolvedClientSecret = clientSecret.trim() || undefined;

		const manualInput = this.ctx.oauthManualInput;
		let manualInputClaim: { promise: Promise<string>; clear: (reason?: string) => void } | undefined;
		const oauthTimeout = new AbortController();
		// Esc, external aborts, and a replacement MCP flow route through here;
		// the timeout path sets its own reason and leaves this flag false so the
		// catch can distinguish cancellation (status) from deadline failure.
		let cancellationRequested = false;
		const requestCancellation = (reason: string): void => {
			cancellationRequested = true;
			if (!oauthTimeout.signal.aborted) oauthTimeout.abort(reason);
		};

View on GitHub (pinned to 9690622007)

Solutions

  1. Check both URLs printed in the error and ensure each is a full absolute URL including scheme (https://...) and host
  2. Fix the config entry or re-run the MCP OAuth setup command with corrected URLs
  3. Test the URLs in a browser or with `new URL(url)` in a script before re-running setup

Example fix

// before
authUrl = "auth.example.com/authorize"; // missing scheme
// after
authUrl = "https://auth.example.com/authorize";
Defensive patterns

Strategy: validation

Validate before calling

function isValidUrl(u: string): boolean {
  try { new URL(u); return true; } catch { return false; }
}
if (!isValidUrl(authUrl) || !isValidUrl(tokenUrl)) {
  console.error('Both authUrl and tokenUrl must be absolute URLs (https://...)');
  return;
}

Try / catch

try {
  await startMcpOAuth({ authUrl, tokenUrl });
} catch (err) {
  if (err instanceof Error && err.message.startsWith('Invalid OAuth URLs')) {
    // prompt user to correct config
  }
}

Prevention

When it happens

Trigger: Running MCP OAuth setup with an authorization URL or token URL that is not a valid absolute URL — e.g. missing https:// scheme, 'localhost:8080' without scheme, or a truncated paste.

Common situations: Copy-pasting URLs from provider docs and dropping the scheme; hand-editing config files and leaving a placeholder; using a relative path like '/oauth/authorize' instead of a full URL.

Related errors


AI-assisted analysis of can1357/oh-my-pi@9690622007 (2026-08-31). Data as JSON: /api/errors/5db53e8e10202687. Report an issue: GitHub.