decolua/9router · error · Error

No authorization code received

Error message

No authorization code received

What it means

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.

Source

Thrown at src/lib/oauth/utils/server.js:221

      if (url.pathname !== "/callback" && url.pathname !== "/auth/callback") {
        res.writeHead(404);
        res.end("Not found");
        return;
      }

      const code = url.searchParams.get("code");
      const state = url.searchParams.get("state");
      const errorParam = url.searchParams.get("error");
      const session = state ? pendingExchanges.get(state) : null;

      // Mode A: server-side exchange (session registered)
      if (session) {
        try {
          if (errorParam) {
            throw new Error(url.searchParams.get("error_description") || errorParam);
          }
          if (!code) throw new Error("No authorization code received");

          // Lazy import to avoid circular deps
          const { exchangeTokens } = await import("../providers.js");
          const { createProviderConnection } = await import("@/models");

          const tokenData = await exchangeTokens(
            "codex",
            code,
            session.redirectUri,
            session.codeVerifier,
            state
          );
          const connection = await createProviderConnection({
            provider: "codex",
            authType: "oauth",
            ...tokenData,
            expiresAt: tokenData.expiresIn
              ? new Date(Date.now() + tokenData.expiresIn * 1000).toISOString()

View on GitHub (pinned to 90b52e06ff)

Solutions

  1. Re-run the Codex OAuth flow and let the provider redirect naturally — don't open or refresh the callback URL manually
  2. Verify the authorize request uses response_type=code and a redirect_uri the provider will append the code to
  3. Check no browser extension, shortener, or proxy is stripping query parameters on the 127.0.0.1:1455 redirect
  4. Ensure only one OAuth flow runs at a time so the correct session is matched by state
  5. If it persists, confirm the provider's registered redirect URI exactly matches the proxy's /callback path
Defensive patterns

Strategy: try-catch

Validate before calling

// Check the callback carries a code before counting on the exchange.
const params = new URL(callbackUrl, 'http://localhost').searchParams;
if (!params.get('code')) {
  console.log('Callback had no code param — restart the OAuth flow.');
}

Try / catch

const status = getCodexSessionStatus(state);
if (status && status.status === 'error' && status.error === 'No authorization code received') {
  // callback reached the proxy without ?code= — restart the flow
} else if (status && status.status === 'error') {
  throw new Error(status.error);
}

Prevention

When it happens

Trigger: 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.

Common situations: 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.

Related errors


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