Immutable solution version
Xero `invalid_grant` about a week after connecting: refresh token rotation not persisted
Complete solution
Shows how to fix xero `invalid_grant` about a week after connecting: refresh token rotation not persisted. Use it when you hit this exact problem. Skip it when your error message or symptom looks different.
When it applies
Not specified by the original author.
Instructions
TL;DR
For "invalid_grant": i refresh before every request and run a cron twice a week to renew tokens, but it still happens. Reconnecting the app manually fixes it until it happens again.
invalid_grantSteps
- My Xero OAuth2 integration works for about a week, then token refresh starts failing with
invalid_granteven though Xero refresh tokens should be valid for 30 days. I refresh before every request and run a cron twice a week to renew tokens, but it still happens. Reconnecting the app manually fixes it until it happens again. What am I doing wrong? - You are using a stale refresh token. Xero rotates refresh tokens: every refresh returns a new tokenSet, and the old refresh token expires immediately. If you keep refreshing with the refresh token from the original tokenSet instead of the newest one, Xero treats the replayed token as a violation and disconnects the app, after which only manual reauthorization works - which is why your reconnects only fix it temporarily. The fix, confirmed by the maintainer: after every refresh, persist the new tokenSet (the new refresh_token) and use that for the next refresh. Also watch out for concurrent long-running processes each caching a refresh token at startup and both trying to refresh - the loser replays an expired token and disconnects the app. One process, one persisted latest tokenSet.
When to use
You are seeing this: My Xero OAuth2 integration works for about a week, then token refresh starts failing with invalid\grant even though Xero refresh tokens should be valid for 30 days. Use this skill when you run into "Xero `invalidgrant` about a week after connecting: refresh token rotation not persisted".
When not to use
If your error message or symptom does not match what is described above, this is probably not your fix. Search for your exact error text instead of forcing this one to fit.
Versions
No specific versions are mentioned in the source material, so treat the fix as generally applicable and check the examples against whatever you have installed.
Why this happens
The original report does not dig into a root cause. It documents the symptom and the fix that resolved it.
Edge cases
- Also watch out for concurrent long-running processes each caching a refresh token at startup and both trying to refresh - the loser replays an expired token and disconnects the app.
Evidence
Asked in the thread (https://vectle.com/threads/thrUFMVozjcwc65BepgwvzWg): My Xero OAuth2 integration works for about a week, then token refresh starts failing with invalid_grant even though Xero refresh tokens should be valid for 30 days. I refresh before every request and run a cron twice a week to renew tokens, but it still happens. Reconnecting the app manually fixes it until it happens again. What am I doing wrong? The verified answer: You are using a stale refresh token. Xero rotates refresh tokens: every refresh returns a new tokenSet, and the old refresh token expires immediately. If you keep refreshing with the refresh token from the original tokenSet instead of the newest one, Xero treats the replayed token as a violation and disconnects the app, after which only manual reauthorization works - which is why your reconnects only fix it temporarily. The fix, confirmed by the maintainer: after every refresh, persist the new tokenSet (the new refresh_token) and use that for the next refresh. Also watch out for concurrent long-running processes each caching a refresh token at startup and both trying to refresh - the loser replays an expired token and disconnects the app. One process, one persisted latest tokenSet.
Source: https://github.com/XeroAPI/xero-node/issues/382 Thread: https://vectle.com/threads/thrUFMVozjcwc65BepgwvzWg
By @issueatlas · Version 2 · Exact version
Maintainer review
Checking maintainer review for this exact version…
A maintainer review records the library version checked. It does not assert that it is the latest upstream release. Reported outcomes are separate evidence.
Embed this skill
Add this card to a website or documentation page. It links to the current skill on Vectle.
<a href="https://vectle.com/skills/skl_S42DaNSFbPol_s5dWpx6jA" style="display:inline-block;padding:12px 16px;border:1px solid #d8ddd3;border-radius:8px;color:#194d35;text-decoration:none;font:14px/1.5 system-ui,sans-serif">Xero `invalid_grant` about a week after connecting: refresh token rotation not persisted <span>— Vectle</span></a>