{"record":{"id":"12c5abe073d57dd3","repo":"decolua/9router","slug":"autoping-provider-conn-id-refresh-failed","errorCode":null,"errorMessage":"[AutoPing] ${provider}:${conn.id}: refresh failed: ${e.message}","messagePattern":"\\[AutoPing\\] (.+?):(.+?): refresh failed: (.+?)","errorType":"console","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"src/shared/services/quotaAutoPing.js","lineNumber":207,"sourceCode":"  const key = cacheKey(provider, conn.id);\n\n  // resetAt is stable for time-based windows; Codex polls every tick because inactive windows slide forward.\n  const cachedReset = state.resetCache[key];\n  if (!providerConfig.pingWhenResetAtSlides && cachedReset && Date.now() < new Date(cachedReset).getTime() - C.refreshAheadMs) return;\n\n  // Avoid hammering provider auth/quota endpoints if a ping failed recently.\n  if (shouldSkipAfterFailure(state, key)) return;\n\n  const proxyCfg = await deps.resolveConnectionProxyConfig(conn.providerSpecificData);\n  const proxyOptions = buildProxyOptions(proxyCfg);\n\n  let connection = conn;\n  try {\n    const r = await deps.refreshAndUpdateCredentials(connection, false, proxyOptions);\n    connection = r.connection;\n  } catch (e) {\n    state.failureCache[key] = Date.now();\n    console.warn(`[AutoPing] ${provider}:${conn.id}: refresh failed: ${e.message}`);\n    return;\n  }\n\n  const usage = await handler.getUsage(connection.accessToken, proxyOptions);\n  const quotas = usage?.quotas || {};\n  const quota = quotas?.[providerConfig.quotaKey];\n  const resetAt = quota?.resetAt;\n  if (!resetAt) return;\n\n  state.resetCache[key] = resetAt;\n\n  if (providerConfig.skipWhenBlockingQuotaExhausted && hasExhaustedBlockingQuota(quotas, providerConfig.quotaKey)) return;\n  if (isQuotaExhausted(quota)) return;\n\n  const now = Date.now();\n  const resetKey = normalizeResetKey(resetAt);\n  const lastPingedResetKey = connection.lastPingedResetKey || normalizeResetKey(connection.lastPingedResetAt);\n","sourceCodeStart":189,"sourceCodeEnd":225,"githubUrl":"https://github.com/decolua/9router/blob/90b52e06ffd666b7929554211474d01588f6b1f8/src/shared/services/quotaAutoPing.js#L189-L225","documentation":"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.","triggerScenarios":"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.","commonSituations":"Long-lived accounts whose refresh tokens expired; provider rotated client/secret; corporate proxy blocking token endpoints; connection disabled server-side; clock skew invalidating tokens.","solutions":["Re-authenticate the affected provider connection (re-run its OAuth login) to mint fresh tokens.","Check the proxy config for the connection — a broken proxy makes the token refresh endpoint unreachable.","Verify the provider auth endpoint is reachable from this machine (curl the token URL) and retry; the cooldown auto-expires.","If the account was revoked/deleted, remove the connection from the dashboard instead of letting the tick retry."],"exampleFix":null,"handlingStrategy":"retry","validationCode":"// detect stale credentials before the auto-ping tick\nconst conn = conns.find(c => c.id === id);\nconst expiresAt = conn?.providerSpecificData?.expiresAt;\nif (expiresAt && Date.now() > new Date(expiresAt).getTime()) {\n  console.log(\"token expired — trigger manual re-auth before expecting auto-ping\");\n}","typeGuard":null,"tryCatchPattern":"// cooldown applies automatically; detect chronic failures per connection\nconst fails = state.failureCache[cacheKey(provider, connId)];\nif (fails && Date.now() - fails > 3 * C.failureCooldownMs) {\n  console.warn(\"connection keeps failing refresh — re-auth required\");\n}","preventionTips":["Re-run provider OAuth login before refresh tokens expire.","Validate proxy configuration per connection (broken proxy breaks token refresh).","Keep provider client credentials in sync after rotating secrets.","Watch logs for repeated [AutoPing] refresh warnings on the same connection id."],"tags":["oauth","token-refresh","quota","proxy","network"],"backgroundTag":"oauth-token-refresh-failed","analyzedSha":"90b52e06ffd666b7929554211474d01588f6b1f8","analyzedAt":"2026-08-30T21:05:45.952Z","schemaVersion":2},"datasetVersion":"2026-08-30T23:17:21.991Z"}