{"record":{"id":"e36e63ba991192b6","repo":"decolua/9router","slug":"no-authorization-code-received-e36e63","errorCode":null,"errorMessage":"No authorization code received","messagePattern":"No authorization code received","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"src/lib/oauth/utils/server.js","lineNumber":221,"sourceCode":"\n      if (url.pathname !== \"/callback\" && url.pathname !== \"/auth/callback\") {\n        res.writeHead(404);\n        res.end(\"Not found\");\n        return;\n      }\n\n      const code = url.searchParams.get(\"code\");\n      const state = url.searchParams.get(\"state\");\n      const errorParam = url.searchParams.get(\"error\");\n      const session = state ? pendingExchanges.get(state) : null;\n\n      // Mode A: server-side exchange (session registered)\n      if (session) {\n        try {\n          if (errorParam) {\n            throw new Error(url.searchParams.get(\"error_description\") || errorParam);\n          }\n          if (!code) throw new Error(\"No authorization code received\");\n\n          // Lazy import to avoid circular deps\n          const { exchangeTokens } = await import(\"../providers.js\");\n          const { createProviderConnection } = await import(\"@/models\");\n\n          const tokenData = await exchangeTokens(\n            \"codex\",\n            code,\n            session.redirectUri,\n            session.codeVerifier,\n            state\n          );\n          const connection = await createProviderConnection({\n            provider: \"codex\",\n            authType: \"oauth\",\n            ...tokenData,\n            expiresAt: tokenData.expiresIn\n              ? new Date(Date.now() + tokenData.expiresIn * 1000).toISOString()","sourceCodeStart":203,"sourceCodeEnd":239,"githubUrl":"https://github.com/decolua/9router/blob/90b52e06ffd666b7929554211474d01588f6b1f8/src/lib/oauth/utils/server.js#L203-L239","documentation":"The Codex callback proxy handler requires an authorization `code` in the redirect query to perform the server-side token exchange. The callback matched a registered session but carried neither `code` nor `error`, so no exchange is possible and the session is marked failed. This prevents storing a broken/partial connection.","triggerScenarios":"startCodexProxy receives /callback or /auth/callback whose `state` resolves to a pendingExchanges session, but url.searchParams.get('code') is null/empty and no `error` param was sent.","commonSituations":"Someone opened or refreshed the callback URL manually in a browser (no query params); a redirect chain or extension stripped the code query parameter; the provider redirected to the base callback path without appending parameters (redirect_uri/response_type misconfiguration); a stale tab re-hit port 1455 after the original flow already completed and the URL was re-requested without params.","solutions":["Re-run the Codex OAuth flow and let the provider redirect naturally — don't open or refresh the callback URL manually","Verify the authorize request uses response_type=code and a redirect_uri the provider will append the code to","Check no browser extension, shortener, or proxy is stripping query parameters on the 127.0.0.1:1455 redirect","Ensure only one OAuth flow runs at a time so the correct session is matched by state","If it persists, confirm the provider's registered redirect URI exactly matches the proxy's /callback path"],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":"// Check the callback carries a code before counting on the exchange.\nconst params = new URL(callbackUrl, 'http://localhost').searchParams;\nif (!params.get('code')) {\n  console.log('Callback had no code param — restart the OAuth flow.');\n}","typeGuard":null,"tryCatchPattern":"const status = getCodexSessionStatus(state);\nif (status && status.status === 'error' && status.error === 'No authorization code received') {\n  // callback reached the proxy without ?code= — restart the flow\n} else if (status && status.status === 'error') {\n  throw new Error(status.error);\n}","preventionTips":["Never open or refresh the callback URL directly in a browser","Ensure response_type=code and a redirect_uri the provider appends the code to","Avoid redirect chains or extensions that drop query parameters","Run one OAuth flow at a time so the state resolves to the right session","Keep the provider's registered redirect URI identical to the proxy callback path"],"tags":["oauth","codex","missing-parameter","callback-proxy"],"backgroundTag":"oauth-missing-auth-code","analyzedSha":"90b52e06ffd666b7929554211474d01588f6b1f8","analyzedAt":"2026-08-30T21:05:45.952Z","schemaVersion":2},"datasetVersion":"2026-08-30T23:17:21.991Z"}