decolua/9router · warning

[Codex Reset Credits] force refresh failed: ${retryError.mes

Error message

[Codex Reset Credits] force refresh failed: ${retryError.message}

What it means

Not a thrown error but a console.warn logged in the POST handler of the Codex reset-credits route when the OAuth recovery path fails. After a rate-limit-reset credit consumption returns an auth-expired result, the route force-refreshes the OAuth tokens via refreshAndUpdateCredentials and retries consumption; if the refresh or the retry consumption throws, the catch logs this message and falls through to getResponseForConsumeResult with the original failed consumeResult.

Source

Thrown at src/app/api/usage/[connectionId]/codex-reset-credits/route.js:146

    const { isOAuth, proxyOptions } = resolved;

    if (isOAuth) {
      const refreshed = await refreshCodexConnection(connection, proxyOptions);
      if (refreshed.response) return refreshed.response;
      connection = refreshed.connection;
    }

    // Server-generated redeem id prevents client-controlled replay
    const redeemRequestId = crypto.randomUUID();
    let consumeResult = await consumeCodexRateLimitResetCredit(connection.accessToken, redeemRequestId, proxyOptions);

    if (isOAuth && isAuthExpiredResult(consumeResult) && connection.refreshToken) {
      try {
        const retryResult = await refreshAndUpdateCredentials(connection, true, proxyOptions);
        connection = retryResult.connection;
        consumeResult = await consumeCodexRateLimitResetCredit(connection.accessToken, redeemRequestId, proxyOptions);
      } catch (retryError) {
        console.warn(`[Codex Reset Credits] force refresh failed: ${retryError.message}`);
      }
    }

    return getResponseForConsumeResult(consumeResult, redeemRequestId);
  } catch (error) {
    const provider = connection?.provider ?? "unknown";
    console.warn(`[Codex Reset Credits] ${provider}: ${error.message}`);
    return Response.json({ error: error.message }, { status: 500 });
  }
}

View on GitHub (pinned to 90b52e06ff)

Solutions

  1. Re-authenticate the Codex connection: delete and re-add the OAuth account so a fresh refresh token is stored.
  2. Check proxy/network reachability of the OAuth token endpoint and the Codex API from the host, including proxyOptions configuration.
  3. Inspect the logged retryError.message for the underlying cause (e.g. 'invalid_grant' means the refresh token is dead).
  4. Retry the request after confirming credentials; ensure only one instance uses the account to avoid token rotation races.

Example fix

// before
try {
  const retryResult = await refreshAndUpdateCredentials(connection, true, proxyOptions);
  connection = retryResult.connection;
  consumeResult = await consumeCodexRateLimitResetCredit(connection.accessToken, redeemRequestId, proxyOptions);
} catch (retryError) {
  console.warn(`[Codex Reset Credits] force refresh failed: ${retryError.message}`);
}
// after
try {
  const retryResult = await refreshAndUpdateCredentials(connection, true, proxyOptions);
  connection = retryResult.connection;
  consumeResult = await consumeCodexRateLimitResetCredit(connection.accessToken, redeemRequestId, proxyOptions);
} catch (retryError) {
  console.warn(`[Codex Reset Credits] force refresh failed: ${retryError.message}`);
  if (retryError.message.includes("invalid_grant")) {
    await markConnectionNeedsReauth(connection.id); // surface re-auth to dashboard
  }
}
Defensive patterns

Strategy: try-catch

Validate before calling

// Before calling the reset-credits endpoint, verify the connection still has a refresh token
function canRetryOAuth(conn) { return Boolean(conn?.refreshToken); }

Type guard

function hasRefreshToken(conn) { return typeof conn?.refreshToken === "string" && conn.refreshToken.length > 0; }

Try / catch

try {
  const res = await fetch(`/api/usage/${connId}/codex-reset-credits`, { method: "POST" });
  const body = await res.json();
  if (!res.ok || body.error) {
    if (/invalid_grant|refresh/i.test(body.error)) await reauthenticate(connId);
  }
} catch (e) { /* network error — retry with backoff */ }

Prevention

When it happens

Trigger: POST to /api/usage/[connectionId]/codex-reset-credits on an OAuth Codex connection where (a) the access token is expired (isAuthExpiredResult matched), (b) refreshAndUpdateCredentials throws (invalid/revoked refresh token, network failure to the OAuth token endpoint, proxy error), or (c) the retried consumeCodexRateLimitResetCredit call throws (network error to Codex upstream).

Common situations: Expired or revoked refresh tokens on long-idle Codex OAuth accounts; corporate proxy blocking the token endpoint; transient network outage during the retry; refresh token rotated elsewhere (multiple instances sharing one account).

Related errors


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