decolua/9router · error
[Usage] ${provider}: ${error.message}
Error message
[Usage] ${provider}: ${error.message} What it means
The usage-quota endpoint wraps its whole GET handler (credential refresh + provider usage API call) in a try/catch. When any step fails — token refresh, upstream provider usage API, network — it logs '[Usage] <provider>: <message>' and returns a 500 JSON response carrying the raw error message to the dashboard.
Source
Thrown at src/app/api/usage/[connectionId]/route.js:189
// Fetch usage from provider API
let usage = await getUsageForProvider(connection, proxyOptions, { force });
// If provider returned an auth-expired message instead of throwing,
// force-refresh token and retry once (OAuth only)
if (isOAuth && isAuthExpiredMessage(usage) && connection.refreshToken) {
try {
const retryResult = await refreshAndUpdateCredentials(connection, true, proxyOptions);
connection = retryResult.connection;
usage = await getUsageForProvider(connection, proxyOptions, { force });
} catch (retryError) {
console.warn(`[Usage] ${connection.provider}: force refresh failed: ${retryError.message}`);
}
}
return Response.json(usage);
} catch (error) {
const provider = connection?.provider ?? "unknown";
console.warn(`[Usage] ${provider}: ${error.message}`);
return Response.json({ error: error.message }, { status: 500 });
}
}
View on GitHub (pinned to 90b52e06ff)
Solutions
- Re-authorize the provider connection in the dashboard so fresh access/refresh tokens are stored.
- Check the provider name in the log message and verify the provider's usage API is reachable (network/proxy/firewall).
- Delete and re-add the connection if refresh tokens are revoked.
- Update 9Router if the provider changed its quota API endpoint or response format.
Example fix
// before: stale tokens keep failing
{ "providerConnection": { "accessToken": "expired-token", "refreshToken": "revoked" } }
// after: re-authenticated connection
{ "providerConnection": { "accessToken": "fresh-token", "refreshToken": "valid-refresh", "expiresAt": "2026-09-01T00:00:00Z" } } Defensive patterns
Strategy: try-catch
Validate before calling
const conn = await getProviderConnectionById(id);
if (!conn) return Response.json({ error: 'Unknown connection' }, { status: 404 });
const expired = conn.expiresAt && new Date(conn.expiresAt) < new Date();
if (expired && !conn.refreshToken) return Response.json({ error: 'Re-authorize required' }, { status: 401 }); Try / catch
try {
const usage = await getUsageForProvider(provider, credentials);
return Response.json(usage);
} catch (error) {
if (/expired|unauthorized|401|re-authorize/i.test(error.message)) {
return Response.json({ error: 'auth-expired', hint: 'Re-authorize the connection' }, { status: 401 });
}
console.warn(`[Usage] ${provider}: ${error.message}`);
return Response.json({ error: error.message }, { status: 502 });
} Prevention
- Re-authorize provider connections before tokens expire; watch the dashboard's expiry indicators.
- Keep refresh tokens valid — avoid revoking app access in provider account settings.
- Pin/verify proxy settings for providers that require egress through a proxy.
- Update 9Router promptly when providers change their usage/quota APIs.
When it happens
Trigger: GET /api/usage/:connectionId where the connection's executor throws during refreshCredentials (e.g. 'Failed to refresh credentials. Please re-authorize the connection.'), or getUsageForProvider's upstream HTTP call to the provider's quota endpoint fails (401/403/5xx, DNS, proxy failure).
Common situations: Expired OAuth tokens that cannot be auto-refreshed (revoked refresh token); provider changed its usage/quota API URL or response shape; corporate proxy or DATA_DIR-less environment blocking the upstream call; deleted/invalid connection id passed in.
Related errors
- Failed to refresh credentials. Please re-authorize the conne
- refresh token is required
- clientId is required for external_idp refresh
- scope is required for external_idp refresh
- `Windsurf ${path} HTTP ${res.status}: ${text.slice(0, 200)}`
AI-assisted analysis of decolua/9router@90b52e06ff (2026-08-30).
Data as JSON: /api/errors/c4adb6ef3b1adbd9.
Report an issue: GitHub.