generated client never handled refresh token rotation - the provider rotates on every use and the second refresh 401d
Handles rotating refresh tokens: persist the new token from each refresh. Use when the second refresh 401s. Not for expired tokens.
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
first refresh worked, second refresh: 401 invalid_grantSteps
- Check whether the refresh response includes a new refresh token Expected: you confirm rotation is on.
- Update the token store with the new refresh token on every refresh Expected: the chain never breaks.
- Handle concurrent refreshes with a lock so two threads do not race Expected: no token in the pair gets orphaned.
- 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