decolua/9router · error · Error
${callbackParams.error_description || callbackParams.error}
Error message
${callbackParams.error_description || callbackParams.error} What it means
During the Codex (OpenAI) OAuth flow in CodexService.connect(), the local callback server (port 1455) received a redirect from OpenAI's authorization endpoint carrying error/error_description query parameters instead of an authorization code. This means the authorization server itself rejected the user's consent/login attempt, and the library re-throws the provider's message verbatim. It is thrown before any code exchange happens.
Source
Thrown at src/lib/oauth/services/codex.js:120
await new Promise((resolve, reject) => {
const timeout = setTimeout(() => {
reject(new Error("Authentication timeout (5 minutes)"));
}, 300000);
const checkInterval = setInterval(() => {
if (callbackParams) {
clearInterval(checkInterval);
clearTimeout(timeout);
resolve();
}
}, 100);
});
close();
if (callbackParams.error) {
throw new Error(callbackParams.error_description || callbackParams.error);
}
if (!callbackParams.code) {
throw new Error("No authorization code received");
}
spinner.start("Exchanging code for tokens...");
// Exchange code for tokens (Codex uses form-urlencoded)
const tokens = await this.exchangeCode(callbackParams.code, redirectUri, codeVerifier, "application/x-www-form-urlencoded");
spinner.text = "Saving tokens to server...";
// Save tokens to server
await this.saveTokens(tokens);
spinner.succeed("Codex connected successfully!");
return true;View on GitHub (pinned to 90b52e06ff)
Solutions
- Read the thrown message — it is the raw OAuth error_description (e.g. 'access_denied', 'unauthorized_client') and states exactly why the provider refused.
- Re-run connect() and complete (do not cancel) the OpenAI consent screen in the browser that opens.
- Verify CODEX_CONFIG (clientId, authorizeUrl, scope, extraParams) in src/lib/oauth/constants/oauth.js still matches OpenAI's current OAuth client registration.
- Confirm the redirect_uri (http://localhost:1455/auth/callback) is what OpenAI expects and that nothing else is bound to port 1455.
Example fix
// before: flow throws raw provider error
if (callbackParams.error) {
throw new Error(callbackParams.error_description || callbackParams.error);
}
// after: give actionable context
if (callbackParams.error) {
throw new Error(
`OpenAI authorization failed (${callbackParams.error}): ${callbackParams.error_description || "no description"}. Re-run connect() and approve the consent screen.`
);
} Defensive patterns
Strategy: validation
Validate before calling
// after receiving callback params, before proceeding:
if (callbackParams.error) {
console.error("Provider refused authorization:", callbackParams.error, callbackParams.error_description);
process.exitCode = 1;
} else if (!callbackParams.code) {
console.error("Callback missing authorization code");
} Type guard
function hasOAuthCode(params) {
return !!params && typeof params === "object" && typeof params.code === "string" && params.code.length > 0 && !params.error;
} Try / catch
try {
await codexService.connect();
} catch (err) {
if (/access_denied|unauthorized_client|invalid_request/.test(err.message)) {
console.error("Authorization was rejected by OpenAI. Re-run connect() and approve the consent screen.", err.message);
} else throw err;
} Prevention
- Always complete the consent screen; do not cancel or close the browser tab mid-flow.
- Keep port 1455 free — stop other Codex-like tools before running connect().
- Keep CODEX_CONFIG client registration values in sync with the current OpenAI CLI OAuth client.
- Surface error_description to end users verbatim; it names the exact provider-side reason.
When it happens
Trigger: Calling connect() (src/lib/oauth/services/codex.js:120) when the browser redirect back to http://localhost:1455/auth/callback contains error params — e.g. user clicked 'Cancel'/'Deny' on the OpenAI consent screen (access_denied), the client_id in CODEX_CONFIG is no longer valid, the redirect_uri doesn't match a registered one, or the state/PKCE parameters were rejected.
Common situations: Users deny the consent dialog or close it in a way that redirects back with an error; the bundled OpenAI client ID/authorize URL changed upstream; a proxy or hosts override breaks the localhost redirect; running the flow on a machine where the fixed port 1455 is used by another tool and the callback lands on the wrong server.
Related errors
- Kiro tool input must be a JSON object
- No Codex access token available. Please re-authorize the con
- Missing accessToken
- Failed to save tokens
- No authorization code received
AI-assisted analysis of decolua/9router@90b52e06ff (2026-08-30).
Data as JSON: /api/errors/30876d9e7763259c.
Report an issue: GitHub.