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
- Read the inner error.message after the colon — it names the real failure (timeout, 401, JSON parse)
- Re-authorize the Codex/ChatGPT connection to get a fresh access token
- Ensure providerSpecificData contains the Codex account id expected by getCodexAccountId
- 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
- Always read the inner message after the wrapper prefix — it names the true cause
- Refresh Codex tokens proactively before expiry
- Populate providerSpecificData with the Codex account id at connection time
- Handle dashboard display of usage errors gracefully instead of crashing the panel
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
- ${data?.message || data?.error || data?.detail || `Codex res
- Failed to consume Codex reset credit: ${error.message}
- Cursor AgentService request failed: ${error.message}
- Kiro tool input must be a JSON object
- Failed to fetch image: ${res.status}
AI-assisted analysis of decolua/9router@90b52e06ff (2026-08-30).
Data as JSON: /api/errors/f4bffcd99433031d.
Report an issue: GitHub.