Setup: App using expiring offline access tokens, refreshing server-side near expiry with grant_type=refresh_token against POST /admin/oauth/access_token.
Issue: for a brief window this endpoint returned HTTP 520 (“error code: 520”) for a shop:
[2026-06-15 10:54:07 UTC] POST https://{shop}.myshopify.com/admin/oauth/access_token -> 520 <none>
[2026-06-15 10:54:25 UTC] POST https://{shop}.myshopify.com/admin/oauth/access_token -> 520 <none>
After that, the shop’s offline token was permanently orphaned — every subsequent refresh returned:
POST https://{shop}.myshopify.com/admin/oauth/access_token -> 401
{"error":"invalid_request","error_description":"This request requires an active refresh_token"}
Refresh tokens are single-use / rotating, so it looks like the 520 hit after the old token was consumed/rotated server-side but before the new token was returned — leaving the token gone with no way to recover via refresh_token. The merchant was locked out for ~2 hours until we re-minted via token exchange.
Flagging the 520s on the token endpoint so the team can take a look — a server error there shouldn’t happen, and during refresh rotation it can permanently lock a merchant out. Happy to share exact timestamps / shop / request IDs.
This is actually my biggest concern with expiring token migrations. At the beginning of June, I was about to migrate users on one of my apps when Shopify experienced a major API outage. The same thing happened again this morning: I was preparing another migration and started seeing intermittent API failures with responses such as “Internal error. Looks like something went wrong on our end” with a request ID to forward to the Shopify support.
If these failures occur during the refresh token rotation process, the consequences can be severe. My concern is that a refresh token could be consumed server-side while the response never reaches the app due to a timeout, 520, or internal error. In that scenario, the merchant could end up permanently locked out and forced to reinstall the app to obtain a new token.
For large-scale migrations, that’s a pretty scary failure mode. We really need a mechanism that guarantees token refreshes are atomic and recoverable, even when Shopify or the network experiences transient failures. A server-side error during token rotation should never leave an app without a valid way to authenticate.
The shop then sat idle (no API calls), so no refresh happened during the normal near-expiry window.
The refresh fired lazily on the merchant’s first request after reopening the app the two 520s were at 10:54:07 and 10:54:25 UTC, i.e. ~6h50m after the access token had already expired.
So this wasn’t a near-boundary race (token expiring mid-flight). The access token was stale-and-unused, and the very first refresh attempt to revive it is the one that caught the transient 520 which then consumed/rotated the refresh token without returning the replacement.
we have had a similar issue, access token expired about a week ago, refresh token still 3 months til expiry, unfortunately wasn’t able to get the error message, but we do retry if any issues and have ended up with stale access and refresh tokens.