decolua/9router · error · Error

Failed to fetch Codex usage: ${error.message}

Error message

Failed to fetch Codex usage: ${error.message}

What it means

getCodexUsage aggregates Codex rate-limit and quota information from ChatGPT backend endpoints. Any failure inside the aggregation — network error, bad token, unexpected response shape — is wrapped and rethrown as this error with the original message appended. It is a catch-all wrapper, so the inner message carries the real cause.

Source

Thrown at open-sse/services/usage/codex.js:134

    const reviewRateLimit = getCodexReviewRateLimit(data);
    const sparkRateLimit = getCodexSparkRateLimit(data);
    const availableResetCredits = Math.max(0, toFiniteNumber(data.rate_limit_reset_credits?.available_count, 0));
    const quotas = {};

    appendCodexQuotaWindows(quotas, "", normalRateLimit);
    appendCodexQuotaWindows(quotas, "review", reviewRateLimit);
    appendCodexQuotaWindows(quotas, "spark", sparkRateLimit);

    return {
      plan: data.plan_type || data.summary?.plan || "unknown",
      limitReached: getCodexRateLimitBody(normalRateLimit)?.limit_reached || false,
      reviewLimitReached: getCodexRateLimitBody(reviewRateLimit)?.limit_reached || false,
      sparkLimitReached: getCodexRateLimitBody(sparkRateLimit)?.limit_reached || false,
      resetCredits: { availableCount: availableResetCredits },
      quotas,
    };
  } catch (error) {
    throw new Error(`Failed to fetch Codex usage: ${error.message}`);
  }
}

export async function getCodexRateLimitResetCredits(accessToken, proxyOptions = null, providerSpecificData = null) {
  if (!accessToken) {
    throw new Error("No Codex access token available. Please re-authorize the connection.");
  }

  const accountId = getCodexAccountId(providerSpecificData);
  const headers = {
    "Authorization": `Bearer ${accessToken}`,
    "Accept": "application/json",
    "OpenAI-Beta": "codex-1",
    "originator": "codex_cli_rs",
  };
  if (accountId) headers["ChatGPT-Account-ID"] = accountId;

  const response = await proxyAwareFetch(CODEX_CONFIG.resetCreditsUrl, {

View on GitHub (pinned to 90b52e06ff)

Solutions

  1. Read the inner error.message after the colon — it names the real failure (timeout, 401, JSON parse)
  2. Re-authorize the Codex/ChatGPT connection to get a fresh access token
  3. Ensure providerSpecificData contains the Codex account id expected by getCodexAccountId
  4. Retry on transient network errors; verify proxy configuration if behind a corporate proxy

Example fix

// before
const usage = await getCodexUsage(accessToken, proxyOptions, data);
// after
let usage;
try {
  usage = await getCodexUsage(accessToken, proxyOptions, data);
} catch (e) {
  if (/re-authorize|401|403/i.test(e.message)) {
    accessToken = await refreshCodexToken(connection);
    usage = await getCodexUsage(accessToken, proxyOptions, data);
  } else throw e;
}
Defensive patterns

Strategy: try-catch

Validate before calling

if (!accessToken) {
  throw new Error('Codex connection not authorized; skipping usage fetch.');
}
if (!getCodexAccountId(providerSpecificData)) {
  throw new Error('Codex account id missing from providerSpecificData.');
}

Type guard

function codexReady(token, data) {
  return typeof token === 'string' && token.length > 0 &&
    Boolean(data && typeof data.accountId === 'string' && data.accountId);
}

Try / catch

try {
  usage = await getCodexUsage(accessToken, proxyOptions, data);
} catch (e) {
  const inner = e.message.replace(/^Failed to fetch Codex usage:\s*/, '');
  if (/401|403|re-authorize/i.test(inner)) { accessToken = await refreshCodexToken(conn); usage = await getCodexUsage(accessToken, proxyOptions, data); }
  else if (/fetch|network|timeout/i.test(inner)) { await backoff(); usage = await getCodexUsage(accessToken, proxyOptions, data); }
  else throw e;
}

Prevention

When it happens

Trigger: Any underlying failure while fetching Codex usage: fetch rejects (network/DNS/proxy), access token is expired (401/403), required account id missing, or rate-limit body shapes are missing causing a parse error.

Common situations: ChatGPT/Codex OAuth token expired and not refreshed; codex account data (account_id) absent from providerSpecificData; backend endpoint changed; connectivity issues through a proxy.

Understand the failure class

Background: "API error: {status}" and "HTTP 401/403/404/429/5xx" errors: non-2xx HTTP responses explained — this error's family across 27 libraries.

Related errors


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