decolua/9router · error · Error
No authorization URL returned from OAuth provider
Error message
No authorization URL returned from OAuth provider
What it means
Generic guard when /authorize returns no authUrl and the provider is not a known device-code provider. The modal refuses to call window.open(null) (browsers coerce null to the relative URL ".../null"), so it throws instead. It indicates the server-side authorize step produced no redirect target for an authorization-code provider.
Source
Thrown at src/shared/components/OAuthModal.js:367
throw new Error("Port 56121 in use; close the conflicting process and retry");
}
} catch (e) {
if (e?.message) throw e;
xaiProxyActive = false;
}
}
setAuthData({ ...data, redirectUri, codexServerSide, xaiServerSide });
// Guard: device_code providers return authUrl:null from /authorize. Never window.open(null)
// (browsers coerce it to the relative path ".../null").
if (!data.authUrl) {
if (data.flowType === "device_code") {
throw new Error(
`Provider ${provider} uses device-code login but is not wired in the OAuth modal device-code list`
);
}
throw new Error("No authorization URL returned from OAuth provider");
}
if (provider === "codex" && codexProxyActive) {
// Proxy active: callback will be handled server-side (auto-exchange) or via channels (fallback)
setStep("waiting");
popupRef.current = window.open(data.authUrl, "oauth_popup", "width=600,height=700");
if (!popupRef.current) {
setStep("input");
}
} else if (provider === "xai" && xaiProxyActive) {
setStep("waiting");
popupRef.current = window.open(data.authUrl, "oauth_popup", "width=600,height=700");
if (!popupRef.current) {
setStep("input");
}
} else if (!isLocalhost || provider === "codex" || provider === "xai") {
// Non-localhost or proxy failed: manual input mode
setStep("input");View on GitHub (pinned to 90b52e06ff)
Solutions
- Check the /authorize response body (authUrl, flowType) to see what the server produced
- Verify the provider is fully configured (client_id/secret) in gateway settings
- Confirm the provider's registry entry implements the authorization-code flow
- Report/fix the provider's authorize handler if authUrl is legitimately null
Example fix
null
Defensive patterns
Strategy: validation
Validate before calling
const data = await res.json();
if (!data || typeof data.authUrl !== 'string' || !data.authUrl.startsWith('http')) {
throw new Error('Provider did not return a valid authUrl');
} Type guard
const hasAuthUrl = (d) => !!d && typeof d.authUrl === 'string' && d.authUrl.length > 0;
Try / catch
try {
await startOAuthFlow();
} catch (e) {
if (e.message.includes("No authorization URL")) {
// check provider config; suggest re-configuring the provider
}
} Prevention
- Fully configure the provider (client_id/secret) before attempting login
- Keep gateway and dashboard versions in sync
- Verify /authorize returns authUrl for authorization-code providers via a quick curl
When it happens
Trigger: GET /api/oauth/{provider}/authorize returned 200 but with authUrl:null/absent and flowType !== "device_code" — e.g. a misconfigured provider entry, an authorize handler bug, or an unknown provider id falling through to a stub handler.
Common situations: Provider registry entry missing an OAuth authorize implementation; partially configured provider (no client_id so no URL can be built); version mismatch between registry and dashboard after an upgrade.
Related errors
- No Zed organization selected
- No Google Cloud Project found. Please ensure you have a GCP
- ${data.error_description || data.error}
- `Provider ${provider} uses device-code login but is not wire
- Kiro tool input must be a JSON object
AI-assisted analysis of decolua/9router@90b52e06ff (2026-08-30).
Data as JSON: /api/errors/1a6b3ee32e636450.
Report an issue: GitHub.