Source: https://cli.nylas.com/guides/fix-invalid-grant-error

# Fix the OAuth invalid_grant Error (Email)

The invalid_grant error is OAuth's most confusing failure because the same string covers half a dozen unrelated causes. It almost always means the refresh token can no longer be exchanged — the user revoked access, changed their password, the token expired from disuse, or the server clock drifted. This guide maps each cause to its fix, explains why retrying never helps, and shows how to detect and recover a broken grant with a single re-authentication.

Written by [Pouya Sanooei](https://cli.nylas.com/authors/pouya-sanooei) Software Engineer

Updated June 8, 2026

> **TL;DR:** `invalid_grant` means the refresh token can't be exchanged anymore. The common causes: the user revoked access, changed their password, the token expired from long disuse, the grant was already used once (one-time codes), or the server clock is skewed. Only clock skew is fixable without the user; the rest require fresh consent. Recover by reconnecting with `nylas auth login`.

Command references used in this guide: [`nylas auth status`](https://cli.nylas.com/docs/commands/auth-status), [`nylas auth login`](https://cli.nylas.com/docs/commands/auth-login), and [`nylas doctor`](https://cli.nylas.com/docs/commands/doctor).

## What does invalid_grant mean?

`invalid_grant` is the OAuth 2.0 token-endpoint error returned when the grant you presented — usually a refresh token or an authorization code — is no longer valid. It's defined in [RFC 6749, section 5.2](https://datatracker.ietf.org/doc/html/rfc6749#section-5.2) as covering an expired, revoked, malformed, or otherwise invalid grant. The frustrating part is that one error code hides several distinct failures.

Because it's terminal, retrying the same exchange will never succeed — the token is dead, not rate-limited. The right response is to identify which cause you're hitting, fix the one fixable case (clock skew), and for the rest, get the user to consent again. Treat `invalid_grant` as “reconnect required,” not “try again later.”

## What causes invalid_grant?

The causes fall into a short list, and each maps to a clear fix. The table covers the five common ones. Note that four of the five can only be resolved by fresh user consent — there's no server-side workaround for a token the provider has decided is dead, which is the point of the design.

| Cause | Fix |
| --- | --- |
| User revoked access | Reconnect (fresh consent) |
| Password changed | Reconnect (fresh consent) |
| Token expired from disuse | Reconnect (fresh consent) |
| Auth code reused | Use a new code (one-time only) |
| Server clock skew | Sync the clock (NTP) |

Clock skew is the sneaky one: if your server's time drifts more than a few minutes, the provider rejects the token request as out of its validity window. Sync with NTP and the error disappears with no re-consent needed. Every other row needs the user back in the loop.

## How do you diagnose a broken grant?

Diagnose with `nylas auth status` and `nylas doctor`. The status reports whether the active grant is healthy or needs re-authentication, so you can tell a dead grant from a transient API error. `nylas doctor` runs broader environment checks — connectivity, configuration, and grant state — and surfaces the specific problem instead of a bare error string.

In an application, catch `invalid_grant` from a token refresh and mark that grant as needing reconnection rather than retrying. Surfacing “please reconnect your mailbox” to the user is the correct UX, because the platform genuinely cannot recover a revoked token on its own. Log the failure once; don't loop on it.

```bash
# Check whether the grant is healthy or needs re-auth
nylas auth status
nylas doctor --json | jq '.checks'
```

## How do you recover the grant?

Recover by reconnecting the mailbox with `nylas auth login`, which walks the user through fresh consent and issues a new grant with a working refresh token. This is the only fix for a revoked or expired token — there's no programmatic recovery, by design, because the provider has invalidated the old credential on purpose. After reconnecting, the failing command works again immediately.

Prevent repeat failures by handling the root cause: keep server clocks synced, prompt users to reconnect promptly when a grant dies, and let the platform manage routine token refresh so tokens don't expire from neglect. For the mechanics of how refresh normally keeps a grant alive, see the [refresh token management guide](https://cli.nylas.com/guides/refresh-token-management).

```bash
# The fix for a dead refresh token: reconnect the mailbox
nylas auth login --provider google

# Confirm the new grant is healthy
nylas auth status
```

## Next steps

- [Refresh token management](https://cli.nylas.com/guides/refresh-token-management) — how tokens stay alive between sessions
- [OAuth scopes for email](https://cli.nylas.com/guides/oauth-scopes-for-email-explained) — what a grant is allowed to do
- [Monitor email integration health](https://cli.nylas.com/guides/monitor-email-integration-health-cli) — catch dead grants early
- [Handle email API outages](https://cli.nylas.com/guides/handle-email-api-outages) — distinguish auth failures from outages
- [Fix 'OAuth token expired' (401)](https://cli.nylas.com/guides/fix-oauth-token-expired) — the access-token symptom vs a dead refresh token
- [Full command reference](https://cli.nylas.com/docs/commands) — every flag and subcommand documented
