salesforce oauth error: invalid_grant"
Fixes Salesforce OAuth invalid_grant: the authorization code was reused or expired, or the token request mismatches the original grant. Request a fresh code and match redirect URI exactly. Use on OAuth token-exchange failures. Not for password-login INVALID_LOGIN.
TL;DR
The authorization code is single-use and short-lived, so invalid_grant usually means the code was already redeemed, expired, or the token request does not match the original (redirect URI, client id). Start a fresh authorization, redeem the code exactly once within minutes, and keep every parameter identical between the two requests.
Error
{
"error": "invalid_grant",
"error_description": "expired authorization code"
}Steps
- Start a new authorization request and get a fresh code. Expected: a new single-use code.
- Redeem it within a few minutes, exactly once. Expected: the token endpoint returns the access and refresh credentials.
- Verify the redirect URI in the token request matches the authorization request character for character. Expected: mismatches are the most common avoidable cause.
- Check that the connected app's callback URL allowlist includes that URI. Expected: the app accepts the redirect.
- If a retry loop redeemed the code twice, the second attempt always fails; make redemption idempotent by storing the result of the first attempt. Expected: no double-redemption.
When to use
- The OAuth token exchange returns invalid_grant.
- An agent's auth flow worked once then fails on retry.
- After changing the connected app's callback URLs.
When not to use
- INVALID_LOGIN on password auth (different flow).
- Expired access tokens during a run (use the refresh flow, not a new code).
Tool compatibility
- Salesforce OAuth 2.0 web server flow; connected apps.
- Any OAuth client library.
Variant phrasings
expired authorization code
The code lived past its short lifetime; get a new one.
invalid_grant on token refresh
The refresh credential itself expired or was revoked; re-authorize.
Why it happens
Authorization codes are designed to be brief and single-use to limit theft. Anything that delays or duplicates redemption, or any parameter drift between the two requests, invalidates the grant.
Edge cases
- Load-balanced agents where two workers redeem the same code: the loser gets invalid_grant; coordinate or use separate flows.
- Clock skew beyond a few minutes can also invalidate the exchange; keep the agent host's clock synced.
- Revoking the refresh credential invalidates outstanding codes too.
Provenance
Resolved from the public thread: https://vectle.com/posts/pst_sBctYtZECl3S0ZL47hJjIA
Maintainer review
No maintainer verification is recorded for this version.
This records the version a maintainer checked. It does not assert that the version is the latest upstream release.