slopus/happy · error
No authorization code received
Error message
No authorization code received
What it means
In the Codex OAuth callback handler, after the `state` check passes, the server verifies that an authorization `code` query parameter is present. The authorization code is what gets exchanged at https://auth.openai.com/oauth/token for access/ID/refresh tokens. If the redirect arrived without a `code`, the flow cannot continue and the promise is rejected with 'No authorization code received'.
Source
Thrown at packages/happy-cli/src/commands/connect/authenticateCodex.ts:163
): Promise<CodexAuthTokens> {
return new Promise((resolve, reject) => {
const server = createServer(async (req: IncomingMessage, res: ServerResponse) => {
const url = new URL(req.url!, `http://localhost:${port}`);
if (url.pathname === '/auth/callback') {
const code = url.searchParams.get('code');
const receivedState = url.searchParams.get('state');
if (receivedState !== state) {
res.writeHead(400);
res.end('Invalid state parameter');
server.close();
reject(new Error('Invalid state parameter'));
return;
}
if (!code) {
res.writeHead(400);
res.end('No authorization code received');
server.close();
reject(new Error('No authorization code received'));
return;
}
try {
// Exchange code for tokens
const tokens = await exchangeCodeForTokens(code, verifier, port);
// Send success response to browser
res.writeHead(200, { 'Content-Type': 'text/html' });
res.end(`
<html>
<body style="font-family: sans-serif; padding: 20px;">
<h2>✅ Authentication Successful!</h2>
<p>You can close this window and return to your terminal.</p>
<script>setTimeout(() => window.close(), 3000);</script>View on GitHub (pinned to b824cd0a46)
Solutions
- Check the full callback URL (the browser tab shows it) for `error=` parameters — if the user denied access, re-run connect and approve the consent screen.
- Retry `happy` connect from scratch; authorization codes are single-use and expire within minutes.
- Verify no proxy or rewrite rule strips the `code` query parameter on localhost callbacks.
- If it reproduces consistently, confirm the CLI's bundled client_id/redirect flow is unchanged and you are on a current happy-cli version.
Defensive patterns
Strategy: try-catch
Try / catch
try {
const tokens = await authenticateCodex();
} catch (err) {
if (err instanceof Error && err.message === 'No authorization code received') {
// user denied consent or provider returned an error redirect; prompt and retry once
console.error('Authorization was not granted (check the callback URL for error=access_denied). Retrying connect...');
} else throw err;
} Prevention
- Complete the consent screen fully; do not cancel or dismiss the OpenAI authorization dialog.
- Treat authorization codes as single-use: never reload or re-open a callback URL.
- If connect fails repeatedly, inspect the callback URL's query string for `error` parameters before retrying.
- Retry from a fresh flow immediately — codes expire within minutes.
When it happens
Trigger: The identity provider redirects to /auth/callback with a valid state but no `code` parameter — typically because the provider appended `error=access_denied` (or another error) instead of a code, because the user denied consent, or because the authorization request was malformed (bad client_id, redirect_uri mismatch) so no code was issued.
Common situations: User clicks 'Cancel'/'Deny' on the OpenAI consent screen; the OAuth app's registered redirect URI doesn't match http://localhost:<port>/auth/callback so the provider redirects with an error; expired or single-use authorization URL is hit twice (code already consumed and not re-issued).
Related errors
- No authorization code received
- No authorization code received
- Token exchange failed: ${tokenResponse.statusText}
- Token exchange failed: ${error}
- Token exchange failed: ${error}
AI-assisted analysis of slopus/happy@b824cd0a46 (2026-08-31).
Data as JSON: /api/errors/ed3e375097b30162.
Report an issue: GitHub.