decolua/9router · error · Error

No authorization code received

Error message

No authorization code received

What it means

In CodexService.connect() (src/lib/oauth/services/codex.js:124), the OAuth callback arrived without an error parameter but also without the expected `code` query parameter. The local server captured callbackParams but OpenAI's redirect did not deliver an authorization code, so the PKCE code exchange cannot proceed and the library aborts.

Source

Thrown at src/lib/oauth/services/codex.js:124

        }, 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;
    } catch (error) {
      spinner.fail(`Failed: ${error.message}`);
      throw error;
    }

View on GitHub (pinned to 90b52e06ff)

Solutions

  1. Re-run connect() and let the browser redirect happen naturally; do not navigate to the callback URL manually.
  2. Log callbackParams (Object.keys) at the local-server handler to see exactly what the provider sent back.
  3. Check for browser extensions or proxies that strip query parameters on localhost redirects and disable them.
  4. Guard the param setter in startLocalServer to ignore subsequent code-less callbacks so a duplicate request cannot overwrite a good one.

Example fix

// before
callbackParams = params;
// after: keep first valid callback
callbackParams = callbackParams || params;
if (params.code) callbackParams = params;
Defensive patterns

Strategy: validation

Validate before calling

const params = new URLSearchParams(callbackUrl.split("?")[1] || "");
if (!params.get("code") && !params.get("error")) {
  console.error("Callback had neither code nor error — check for param-stripping proxies/extensions");
}

Type guard

function hasAuthorizationCode(params) {
  return typeof params === "object" && params !== null && typeof params.code === "string" && params.code.length > 0;
}

Try / catch

try {
  await codexService.connect();
} catch (err) {
  if (err.message === "No authorization code received") {
    console.error("The redirect back to localhost carried no ?code=. Disable extensions/proxies that strip query params and retry.");
  } else throw err;
}

Prevention

When it happens

Trigger: Calling connect() and receiving a callback whose query string lacks `code` — typically a redirect to the callback URL with no OAuth params at all (user manually navigated to http://localhost:1455/auth/callback, or a browser extension/proxy stripped query params), or the provider returned an unexpected response shape that bypassed the error check.

Common situations: The user types or bookmarks the callback URL directly while the local server is listening; a security plugin or corporate proxy rewrites the redirect and drops the query string; the browser opens the callback twice and the second (code-less) hit overwrites callbackParams via the polling checkInterval.

Related errors


AI-assisted analysis of decolua/9router@90b52e06ff (2026-08-30). Data as JSON: /api/errors/70d253f49688f9df. Report an issue: GitHub.