## TL;DR

The stored OAuth credentials expired or were revoked and the refresh attempt failed. Re-authenticate with gcloud auth application-default login, or switch the profile to a service-account key file which does not need interactive refresh. Then dbt debug to confirm.

## Error

```text
dbt-bigquery: oauth token refresh failed
```

## Steps

1. Check which auth method the profile uses: method: oauth with a token file, or a keyfile. For oauth, the refresh token may be revoked or expired.
   Expected: You know whether dbt relies on a user OAuth token or a service account.

2. For user OAuth: run gcloud auth application-default login and complete the browser flow, then re-run dbt debug.
   Expected: Fresh credentials are stored and dbt connects.

3. For a durable fix in CI or team setups, switch the profile to method: service-account with a keyfile JSON, and store the keyfile outside the repo.
   Expected: No interactive refresh needed; CI runs headless reliably.

4. Run dbt debug and then a light dbt compile to confirm the adapter is healthy.
   Expected: Connection passes, compile succeeds.

## When to use

- dbt-bigquery fails with oauth token refresh failed
- local runs break every few weeks (user OAuth tokens expire)
- CI fails on auth while local works (CI has no interactive login)

## When not to use

- service account keyfile not found (that is a file path problem)
- IAM permission denied after connecting (that is grants)
- the error is about quota, not auth

## Tool compatibility

- dbt-bigquery adapter; method oauth vs service-account
- gcloud auth application-default login refreshes user credentials
- dbt Cloud: use its native BigQuery OAuth or service account setup

## Variant phrasings

### token refresh failed in CI only
CI cannot do the browser flow. Service-account keyfile is the answer; never commit the keyfile, inject it as a CI secret.

### refresh failed right after a password change
Google revoked OAuth grants on password change. Re-run the login flow to re-grant.

## Why it happens

User OAuth tokens are short-lived by design and refresh tokens can be revoked by password changes, admin policy, or inactivity. dbt-bigquery with method oauth depends on that refresh succeeding silently, and when it does not, every run fails at connection time.

## Edge cases

- Multiple gcloud accounts on one machine cause the wrong identity to refresh; check gcloud auth list matches the intended user.
- Service-account keys should be rotated; set a calendar reminder or the same failure returns on rotation day.

## Provenance

Resolved from the public thread: https://vectle.com/posts/pst_JzLOw09EZiZH2UYJ5Yw8Zw
