decolua/9router · info
[Claude Usage] OAuth endpoint returned ${oauthResponse.statu
Error message
[Claude Usage] OAuth endpoint returned ${oauthResponse.status}, falling back to legacy What it means
fetchClaudeUsageRaw first calls Anthropic's OAuth usage endpoint; on any non-ok status (except the handled 429 cooldown path) it logs this warning and transparently falls back to the legacy settings + org usage endpoint. The value returned to the caller comes from the legacy path, so usage data is usually still available.
Source
Thrown at open-sse/services/usage/claude.js:126
const modelName = key.replace("seven_day_", "");
quotas[`weekly ${modelName} (7d)`] = createQuotaObject(value);
}
}
return {
plan: "Claude Code",
extraUsage: data.extra_usage ?? null,
quotas,
};
}
// Cool down OAuth usage polling after a 429 (quota endpoint only)
if (oauthResponse.status === 429) {
oauthCooldown.set(accessToken, Date.now() + OAUTH_429_COOLDOWN_MS);
}
// Fallback: legacy settings + org usage endpoint
console.warn(`[Claude Usage] OAuth endpoint returned ${oauthResponse.status}, falling back to legacy`);
return await getClaudeUsageLegacy(accessToken, proxyOptions);
} catch (error) {
return { message: `Claude connected. Unable to fetch usage: ${error.message}` };
}
}
/**
* Legacy Claude usage for API key / org admin users
*/
async function getClaudeUsageLegacy(accessToken, proxyOptions = null) {
try {
const settingsResponse = await proxyAwareFetch(CLAUDE_CONFIG.settingsUrl, {
method: "GET",
headers: {
"Authorization": `Bearer ${accessToken}`,
"anthropic-version": CLAUDE_CONFIG.apiVersion,
},
}, proxyOptions);View on GitHub (pinned to 90b52e06ff)
Solutions
- No action needed if the legacy fallback returns data — this is a downgrade warning only
- If fallback also fails, re-authenticate the Claude OAuth connection to get a fresh token
- Confirm the connected account's plan supports the OAuth usage endpoint
- Check Anthropic status/incidents if the status is 5xx
- Verify proxy settings aren't altering the usage request
Example fix
// before: stale token keeps hitting the new endpoint with 401 // after: re-run OAuth to refresh credentials, or shorten refresh interval await refreshToken(connectionId); // before next fetchClaudeUsageRaw call
Defensive patterns
Strategy: fallback
Validate before calling
const conn = await api.get(`/api/connections/${id}`);
if (!conn || conn.tokenExpiresAt < Date.now()) await reauth(id); // refresh before usage fetch Type guard
const hasUsageData = (u) => u && !u.message && typeof u === 'object';
if (!hasUsageData(usage)) console.warn('usage unavailable:', usage?.message); Try / catch
try {
const usage = await fetchClaudeUsageRaw(token);
// legacy fallback already applied internally; validate shape
if (usage?.message) console.warn(usage.message);
return usage;
} catch (e) {
console.warn(`claude usage unavailable: ${e.message}`);
return null;
} Prevention
- Keep OAuth tokens refreshed before polling usage
- Verify the account plan supports the OAuth usage endpoint
- Handle 429 cooldowns — back off instead of hammering the quota endpoint
- Fall back to legacy usage data display when the new endpoint is unavailable
When it happens
Trigger: The OAuth usage endpoint returned 400/401/403/404/5xx — expired OAuth token, account not eligible for the new usage API, region/plan without the endpoint, or transient upstream 5xx.
Common situations: OAuth access token expired or revoked (401); account on a plan that lacks the OAuth usage endpoint (404); Anthropic API change moved/renamed the endpoint; transient 500/503 during Anthropic incidents.
Related errors
- `Token exchange failed: ${error}`
- "No JSON found in decoded code"
- "No JSON found in decoded code"
- `Windsurf ${path} HTTP ${res.status}: ${text.slice(0, 200)}`
- Failed to save tokens
AI-assisted analysis of decolua/9router@90b52e06ff (2026-08-30).
Data as JSON: /api/errors/661f3dcd2bad8e44.
Report an issue: GitHub.