decolua/9router · error · Error
${data?.message || data?.error || data?.detail || `Codex res
Error message
${data?.message || data?.error || data?.detail || `Codex reset credits API unavailable (${response.status}).`} What it means
After calling the Codex reset-credits endpoint, a non-OK response triggers this throw. The message prefers the API's own error text (message/error/detail fields) and falls back to a generic 'unavailable (status)' string. It means the backend refused or failed the reset-credits query.
Source
Thrown at open-sse/services/usage/codex.js:166
"originator": "codex_cli_rs",
};
if (accountId) headers["ChatGPT-Account-ID"] = accountId;
const response = await proxyAwareFetch(CODEX_CONFIG.resetCreditsUrl, {
method: "GET",
headers,
}, proxyOptions);
let data = null;
try {
data = await response.json();
} catch {
data = null;
}
if (!response.ok) {
const message = data?.message || data?.error || data?.detail || `Codex reset credits API unavailable (${response.status}).`;
throw new Error(message);
}
const credits = Array.isArray(data?.credits) ? data.credits : [];
return {
availableCount: Math.max(0, toFiniteNumber(data?.available_count ?? data?.availableCount, 0)),
credits: credits.map((credit) => ({
status: String(credit?.status || "unknown"),
grantedAt: toIsoDate(credit?.granted_at ?? credit?.grantedAt),
expiresAt: toIsoDate(credit?.expires_at ?? credit?.expiresAt),
})),
};
}
// Consume one Codex rate-limit reset credit (irreversible, spends 1 credit)
export async function consumeCodexRateLimitResetCredit(accessToken, redeemRequestId, proxyOptions = null) {
if (!accessToken) {
throw new Error("No Codex access token available. Please re-authorize the connection.");
}View on GitHub (pinned to 90b52e06ff)
Solutions
- If the message is generic (no API text), check response.status in logs — a 401/403 means re-authorize the Codex connection
- Retry on 429/5xx after a backoff window
- Verify the reset-credits endpoint URL in CODEX_CONFIG is still current
- Confirm network/proxy path to the ChatGPT backend is clean
Defensive patterns
Strategy: try-catch
Validate before calling
if (!accessToken) throw new Error('Codex not authorized.');
// optionally probe availability before consuming UI flows:
// const ok = await fetchHealth(CODEX_CONFIG.resetCreditsUrl); Try / catch
try {
credits = await getCodexRateLimitResetCredits(accessToken, proxyOptions, data);
} catch (e) {
const m = /\((\d{3})\)\.$/.exec(e.message); // generic fallback carries the status
const status = m ? Number(m[1]) : null;
if (status === 401 || status === 403) return reauthorizeCodex(conn);
if (status === 429 || (status && status >= 500)) { await backoff(); return retry(); }
throw e;
} Prevention
- Prefer errors that include API-provided text — generic '(status)' messages mean the body did not parse; log raw responses
- Refresh the Codex token before it expires to avoid most 401s
- Back off on 429/5xx instead of hammering the endpoint
- Track ChatGPT backend endpoint changes and update CODEX_CONFIG accordingly
When it happens
Trigger: The reset-credits fetch returns non-2xx: 401/403 expired token, 404 endpoint moved, 429 rate limited, or 5xx ChatGPT backend outage; response body JSON parse failures also funnel into the generic fallback message.
Common situations: Expired Codex access token; ChatGPT backend API changed or is down; account not entitled to reset credits; proxy altering the response.
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
- Failed to fetch Codex usage: ${error.message}
- Failed to fetch image: ${res.status}
- Google translate fetch failed: ${res.status}
- Google TTS failed: ${res.status}
- MiniMax TTS error (${res.status})
AI-assisted analysis of decolua/9router@90b52e06ff (2026-08-30).
Data as JSON: /api/errors/ffd65aeab8730efe.
Report an issue: GitHub.