decolua/9router · error

All accounts unavailable

Error message

All accounts unavailable

What it means

Raised in handleSingleProviderFetch (src/sse/handlers/fetch.js:175-176) when the credential fallback loop is exhausted: excludeConnectionIds is non-empty (at least one account was already tried and failed) and getProviderCredentials can no longer return a usable connection. The gateway has tried each stored account for the provider, each was marked unavailable via markAccountUnavailable, and there is nothing left to try. It returns the last upstream error/status if available, otherwise 503 'All accounts unavailable'.

Source

Thrown at src/sse/handlers/fetch.js:175

  const excludeConnectionIds = new Set();
  let lastError = null;
  let lastStatus = null;

  while (true) {
    const credentials = await getProviderCredentials(providerId, excludeConnectionIds);

    if (!credentials || credentials.allRateLimited) {
      if (credentials?.allRateLimited) {
        const errorMsg = lastError || credentials.lastError || "Unavailable";
        const status = lastStatus || Number(credentials.lastErrorCode) || HTTP_STATUS.SERVICE_UNAVAILABLE;
        log.warn("FETCH", `[${providerId}] ${errorMsg} (${credentials.retryAfterHuman})`);
        return unavailableResponse(status, `[${providerId}] ${errorMsg}`, credentials.retryAfter, credentials.retryAfterHuman);
      }
      if (excludeConnectionIds.size === 0) {
        log.error("AUTH", `No credentials for provider: ${providerId}`);
        return errorResponse(HTTP_STATUS.BAD_REQUEST, `No credentials for provider: ${providerId}`);
      }
      log.warn("FETCH", "No more accounts available", { provider: providerId });
      return errorResponse(lastStatus || HTTP_STATUS.SERVICE_UNAVAILABLE, lastError || "All accounts unavailable");
    }

    log.info("AUTH", `\x1b[32mUsing ${providerId} account: ${credentials.connectionName}\x1b[0m`);

    const refreshedCredentials = await checkAndRefreshToken(providerId, credentials);

    const result = await handleFetchCore({
      url: targetUrl,
      format,
      maxCharacters,
      provider: resolvedProvider.id,
      providerConfig,
      credentials: refreshedCredentials,
      log,
      onCredentialsRefreshed: async (newCreds) => {
        await updateProviderCredentials(credentials.connectionId, {
          accessToken: newCreds.accessToken,

View on GitHub (pinned to 90b52e06ff)

Solutions

  1. Open the dashboard and inspect all connections for that provider; re-authenticate or replace the failing credentials.
  2. Fix the underlying lastError reported in the response (quota, expired token, bad key) for each account before retrying.
  3. Add healthy accounts for the provider so the fallback loop has more than one candidate.
  4. Use a combo spanning different providers so a total failure of one provider falls through to another.
  5. If the accounts are actually fine and were locked by a transient upstream outage, clear the account error state and retry after the upstream recovers.
Defensive patterns

Strategy: fallback

Validate before calling

// Verify the provider has healthy accounts before batching work:
const status = await fetch(base + '/dashboard/api/providers').then(r => r.json());
const p = status.providers?.find(p => p.id === 'exa');
if (!p || p.connections?.every(c => c.status !== 'active')) throw new Error('No healthy accounts for provider');

Try / catch

const res = await doFetch();
if (res.status === 503 && (await res.text()).includes('All accounts unavailable')) {
  return fallbackToAlternateProvider(request);
}
return res;

Prevention

When it happens

Trigger: POST /v1/fetch against a provider with multiple connections where every connection fails in sequence: the first upstream attempt returns a fallback-worthy status (e.g. 429/401/5xx), shouldFallback is true, the connection id is added to excludeConnectionIds, the loop continues, and the next getProviderCredentials call finds no remaining eligible account.

Common situations: Multi-account setups where all keys for a provider expired, were revoked, or hit quota simultaneously (often from a shared IP being throttled upstream); a combo spreading load across accounts of the same dying provider; OAuth connections whose refresh tokens silently expired so every account fails auth on use.

Related errors


AI-assisted analysis of decolua/9router@90b52e06ff (2026-08-30). Data as JSON: /api/errors/c52241514ed64770. Report an issue: GitHub.