docs/proxy-invalid-grant.md
invalid_grant refresh failuresWhen an OAuth refresh_token is revoked/expired, Google token refresh returns invalid_grant.
Previously the proxy could repeatedly pick the same broken account, repeatedly fail refresh, and eventually return a 503 error due to an effectively unusable token pool.
invalid_grantinvalid_grant, the proxy marks that account as disabled on disk:
disabled: truedisabled_at: <unix timestamp>disabled_reason: "invalid_grant: …" (truncated)TokenManager::load_accounts, account JSON files with disabled: true are skipped.Account mutations that affect proxy availability trigger a best-effort token pool reload when the proxy is running:
If a user updates credentials in the UI (token upsert) and changes either refresh_token or access_token, the account is automatically re-enabled by clearing:
disableddisabled_reasondisabled_atThis supports the workflow where a revoked token is replaced manually without requiring a proxy restart.
Accounts gain three new fields:
disabled (bool, default false)disabled_reason (string | null)disabled_at (number | null)These fields are optional and use defaults, so existing account files continue to load.
disabled_reason is truncated to avoid bloating the account JSON.disabled_reason; it is derived from the refresh error string.refresh_token and trigger a proxy request that requires refresh.invalid_grant failure and account disable.