decolua/9router · warning

[AutoPing] ${provider}:${conn.id}: refresh failed: ${e.messa

Error message

[AutoPing] ${provider}:${conn.id}: refresh failed: ${e.message}

What it means

In the quota auto-ping tick, pingConnection first refreshes the connection's OAuth credentials via deps.refreshAndUpdateCredentials. If the refresh throws (invalid/expired refresh token, provider auth endpoint down, network/proxy error, revoked account), the connection key is put in the failure cache (cooldown applied) and this warning is logged; the quota ping is skipped for this tick. It is fail-open: the tick continues with other connections.

Source

Thrown at src/shared/services/quotaAutoPing.js:207

  const key = cacheKey(provider, conn.id);

  // resetAt is stable for time-based windows; Codex polls every tick because inactive windows slide forward.
  const cachedReset = state.resetCache[key];
  if (!providerConfig.pingWhenResetAtSlides && cachedReset && Date.now() < new Date(cachedReset).getTime() - C.refreshAheadMs) return;

  // Avoid hammering provider auth/quota endpoints if a ping failed recently.
  if (shouldSkipAfterFailure(state, key)) return;

  const proxyCfg = await deps.resolveConnectionProxyConfig(conn.providerSpecificData);
  const proxyOptions = buildProxyOptions(proxyCfg);

  let connection = conn;
  try {
    const r = await deps.refreshAndUpdateCredentials(connection, false, proxyOptions);
    connection = r.connection;
  } catch (e) {
    state.failureCache[key] = Date.now();
    console.warn(`[AutoPing] ${provider}:${conn.id}: refresh failed: ${e.message}`);
    return;
  }

  const usage = await handler.getUsage(connection.accessToken, proxyOptions);
  const quotas = usage?.quotas || {};
  const quota = quotas?.[providerConfig.quotaKey];
  const resetAt = quota?.resetAt;
  if (!resetAt) return;

  state.resetCache[key] = resetAt;

  if (providerConfig.skipWhenBlockingQuotaExhausted && hasExhaustedBlockingQuota(quotas, providerConfig.quotaKey)) return;
  if (isQuotaExhausted(quota)) return;

  const now = Date.now();
  const resetKey = normalizeResetKey(resetAt);
  const lastPingedResetKey = connection.lastPingedResetKey || normalizeResetKey(connection.lastPingedResetAt);

View on GitHub (pinned to 90b52e06ff)

Solutions

  1. Re-authenticate the affected provider connection (re-run its OAuth login) to mint fresh tokens.
  2. Check the proxy config for the connection — a broken proxy makes the token refresh endpoint unreachable.
  3. Verify the provider auth endpoint is reachable from this machine (curl the token URL) and retry; the cooldown auto-expires.
  4. If the account was revoked/deleted, remove the connection from the dashboard instead of letting the tick retry.
Defensive patterns

Strategy: retry

Validate before calling

// detect stale credentials before the auto-ping tick
const conn = conns.find(c => c.id === id);
const expiresAt = conn?.providerSpecificData?.expiresAt;
if (expiresAt && Date.now() > new Date(expiresAt).getTime()) {
  console.log("token expired — trigger manual re-auth before expecting auto-ping");
}

Try / catch

// cooldown applies automatically; detect chronic failures per connection
const fails = state.failureCache[cacheKey(provider, connId)];
if (fails && Date.now() - fails > 3 * C.failureCooldownMs) {
  console.warn("connection keeps failing refresh — re-auth required");
}

Prevention

When it happens

Trigger: deps.refreshAndUpdateCredentials(connection, false, proxyOptions) throws during runQuotaAutoPingTick: refresh token expired/revoked, provider OAuth endpoint unreachable, misconfigured proxy in providerSpecificData, or account needs re-login.

Common situations: Long-lived accounts whose refresh tokens expired; provider rotated client/secret; corporate proxy blocking token endpoints; connection disabled server-side; clock skew invalidating tokens.

Related errors


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