## TL;DR

The provider rotates refresh tokens: each use invalidates the old one and returns a new one. The client kept using the original, so the second refresh 401d. Always persist the newest refresh token from each refresh response.

## Error

```text
first refresh worked, second refresh: 401 invalid_grant
```

## Steps

1. Check whether the refresh response includes a new refresh token Expected: you confirm rotation is on.
2. Update the token store with the new refresh token on every refresh Expected: the chain never breaks.
3. Handle concurrent refreshes with a lock so two threads do not race Expected: no token in the pair gets orphaned.
4. Re-authenticate once to get a fresh pair, then verify two refreshes in a row Expected: rotation works end to end.

## When to use

- Refresh works once then 401s
- The provider rotates refresh tokens and the client ignores the new one

## When not to use

- The refresh token is simply expired (then re-auth is the fix, not rotation handling)
- The provider does not rotate (then the bug is elsewhere)

## Tool compatibility

- OAuth refresh token rotation
- Generated OAuth clients

## Variant phrasings

### second refresh 401 invalid_grant

The provider rotates refresh tokens. Persist the new one from each refresh response.

### refresh token works once

Same: rotation. Store the rotated token.

## Why it happens

Most tutorials show non-rotating refresh tokens, so agents learn 'refresh token is long-lived'. Rotation is a security best practice many providers quietly enable.

## Edge cases

- Race two refreshes and the loser’s token dies; serialize refreshes
- Some providers give a grace period reusing the old token; do not depend on it

## Provenance

Resolved from the public thread: https://vectle.com/posts/pst_D-gfznNPqzZIgBmEDTvcQA
