{"record":{"id":"ed3e375097b30162","repo":"slopus/happy","slug":"no-authorization-code-received-ed3e37","errorCode":null,"errorMessage":"No authorization code received","messagePattern":"No authorization code received","errorType":"http","errorClass":null,"httpStatus":400,"severity":"error","filePath":"packages/happy-cli/src/commands/connect/authenticateCodex.ts","lineNumber":163,"sourceCode":"): Promise<CodexAuthTokens> {\n    return new Promise((resolve, reject) => {\n        const server = createServer(async (req: IncomingMessage, res: ServerResponse) => {\n            const url = new URL(req.url!, `http://localhost:${port}`);\n\n            if (url.pathname === '/auth/callback') {\n                const code = url.searchParams.get('code');\n                const receivedState = url.searchParams.get('state');\n\n                if (receivedState !== state) {\n                    res.writeHead(400);\n                    res.end('Invalid state parameter');\n                    server.close();\n                    reject(new Error('Invalid state parameter'));\n                    return;\n                }\n\n                if (!code) {\n                    res.writeHead(400);\n                    res.end('No authorization code received');\n                    server.close();\n                    reject(new Error('No authorization code received'));\n                    return;\n                }\n\n                try {\n                    // Exchange code for tokens\n                    const tokens = await exchangeCodeForTokens(code, verifier, port);\n\n                    // Send success response to browser\n                    res.writeHead(200, { 'Content-Type': 'text/html' });\n                    res.end(`\n                        <html>\n                        <body style=\"font-family: sans-serif; padding: 20px;\">\n                            <h2>✅ Authentication Successful!</h2>\n                            <p>You can close this window and return to your terminal.</p>\n                            <script>setTimeout(() => window.close(), 3000);</script>","sourceCodeStart":145,"sourceCodeEnd":181,"githubUrl":"https://github.com/slopus/happy/blob/b824cd0a4681d41af631a8e422a813873e4455b0/packages/happy-cli/src/commands/connect/authenticateCodex.ts#L145-L181","documentation":"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'.","triggerScenarios":"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.","commonSituations":"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).","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."],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"try {\n  const tokens = await authenticateCodex();\n} catch (err) {\n  if (err instanceof Error && err.message === 'No authorization code received') {\n    // user denied consent or provider returned an error redirect; prompt and retry once\n    console.error('Authorization was not granted (check the callback URL for error=access_denied). Retrying connect...');\n  } else throw err;\n}","preventionTips":["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."],"tags":["oauth","authorization-code","authentication","callback"],"backgroundTag":"missing-oauth-authorization-code","analyzedSha":"b824cd0a4681d41af631a8e422a813873e4455b0","analyzedAt":"2026-08-31T23:12:36.205Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T05:18:18.240Z"}