decolua/9router · error · Error
A redeem request id is required to consume a Codex reset cre
Error message
A redeem request id is required to consume a Codex reset credit.
What it means
consumeCodexRateLimitResetCredit(accessToken, redeemRequestId) requires a redeem request id identifying which reset credit to spend. If redeemRequestId is missing or not a non-empty string, this guard error is thrown before any network call. No credit is consumed in this case.
Source
Thrown at open-sse/services/usage/codex.js:186
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.");
}
if (!redeemRequestId || typeof redeemRequestId !== "string") {
throw new Error("A redeem request id is required to consume a Codex reset credit.");
}
let response;
let data = null;
try {
response = await proxyAwareFetch(CODEX_CONFIG.resetCreditsConsumeUrl, {
method: "POST",
headers: {
"Authorization": `Bearer ${accessToken}`,
"Accept": "application/json",
"Content-Type": "application/json",
},
body: JSON.stringify({ redeem_request_id: redeemRequestId }),
}, proxyOptions);
const text = await response.text();
data = text ? JSON.parse(text) : null;
} catch (error) {View on GitHub (pinned to 90b52e06ff)
Solutions
- Fetch available credits first (getCodexRateLimitResetCredits) and pass one of the returned credit ids as redeemRequestId
- Validate the client request body includes a string redeemRequestId before dispatching to the handler
- Coerce/trim the incoming id and reject empty strings client-side
- Check the credits response schema — take the correct id field from each credit object
Example fix
// before
await consumeCodexRateLimitResetCredit(token, body.id);
// after
if (typeof body.redeemRequestId !== 'string' || !body.redeemRequestId) {
return res.status(400).json({ error: 'redeemRequestId is required' });
}
await consumeCodexRateLimitResetCredit(token, body.redeemRequestId); Defensive patterns
Strategy: validation
Validate before calling
// caller-side validation before invoking
const rid = body?.redeemRequestId;
if (typeof rid !== 'string' || rid.trim() === '') {
return res.status(400).json({ error: 'redeemRequestId (string) is required' });
} Type guard
function isValidRedeemId(id) { return typeof id === 'string' && id.trim().length > 0; } Try / catch
try {
await consumeCodexRateLimitResetCredit(accessToken, redeemRequestId);
} catch (e) {
if (e.message.includes('redeem request id')) {
const credits = await getCodexRateLimitResetCredits(accessToken);
redeemRequestId = credits.credits[0]?.id; // recover by fetching a valid id
if (!redeemRequestId) throw new Error('No reset credits available.');
return consumeCodexRateLimitResetCredit(accessToken, redeemRequestId);
}
throw e;
} Prevention
- Always fetch available credits first and use an id from that response
- Validate request bodies (string, non-empty) before passing ids into service functions
- Never construct redeem ids client-side; they come from the credits API
- No credit is spent when this guard fires — safe to correct inputs and retry
When it happens
Trigger: The consume handler is invoked without a redeemRequestId, with an empty string, or with a non-string value (e.g. a number or object from an unvalidated request body).
Common situations: Client UI calling the consume POST without first fetching available credits to obtain an id; request body field renamed or omitted; id coerced to a number by JSON handling.
Understand the failure class
Background: Missing required parameter errors: what 'X is required' and 'the required X param is missing' mean, and how to fix them — this error's family across 27 libraries.
Related errors
- Item is not an object
- Missing accessToken
- No authorization code received
- No authorization code received
- Kiro tool input must be a JSON object
AI-assisted analysis of decolua/9router@90b52e06ff (2026-08-30).
Data as JSON: /api/errors/8016eb7022c98639.
Report an issue: GitHub.