Source: https://cli.nylas.com/guides/fix-oauth-token-expired

# Fix 'OAuth Token Expired' (401) for Email

A script that worked an hour ago now returns 401 'token expired.' This is the most common OAuth symptom, and it has a precise cause: the short-lived access token aged out and nobody refreshed it. The fix is to refresh — but first you have to tell an expired access token apart from a dead refresh token, because they look similar and have opposite fixes. This guide diagnoses the 401, shows the refresh, and explains how the CLI prevents it from ever firing.

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

Updated June 8, 2026

> **TL;DR:** A `401` “token expired” means the access token aged out — typically after 3,600 seconds — and you simply refresh it with the refresh token. If the refresh itself fails with `invalid_grant`, that's a different, terminal problem requiring re-consent. The Nylas CLI refreshes access tokens automatically behind every command, so this 401 doesn't fire on long-running jobs.

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 email list`](https://cli.nylas.com/docs/commands/email-list).

## What does “token expired” actually mean?

“Token expired” on a `401` means the *access token* — the short-lived credential your code sends on each API call — passed its expiry and the provider rejected it. Access tokens are intentionally short-lived; Google's default lifetime is 3,600 seconds (one hour), and Microsoft's sits in a similar range. The error isn't a sign anything is broken; it's the normal end of a token's life.

The fix is to exchange your refresh token for a new access token and retry the call. This is the routine half of OAuth, defined in [RFC 6749, section 5](https://datatracker.ietf.org/doc/html/rfc6749#section-5): present the refresh token to the token endpoint, receive a fresh access token, continue. Done on a schedule or on demand, expiry becomes invisible to your application.

## How is it different from invalid_grant?

The two look alike but have opposite fixes, so distinguishing them saves real time. A `401` “token expired” is the access token aging out — fixable by a refresh, no user needed. An `invalid_grant` at the token endpoint means the *refresh token* itself is dead — revoked, password-changed, or expired from disuse — and only fresh user consent recovers it. The table makes the split explicit.

| Symptom | What's dead | Fix |
| --- | --- | --- |
| 401 on an API call | Access token (expired) | Refresh; retry (no user) |
| invalid_grant on refresh | Refresh token (revoked/expired) | Re-consent with a new login |

If your refresh call returns `invalid_grant`, stop retrying and reconnect — the detailed causes and recovery are in the [invalid_grant troubleshooting guide](https://cli.nylas.com/guides/fix-invalid-grant-error).

## How does the CLI prevent the 401 entirely?

The CLI prevents this 401 by refreshing the access token for you on every command. A call like `nylas email list` works whether it runs one minute or one week after login, because the platform keeps the access token current behind the grant. The classic “it worked an hour ago” failure simply doesn't occur, since there's no access token in your code to let expire.

Check a grant's health with `nylas auth status`: a healthy grant means refresh is succeeding; a status flagging re-authentication means the refresh token is the dead one, and `nylas auth login` recovers it. That single command tells you which of the two problems you have, so you never confuse an expired access token (no action needed) with a revoked refresh token (reconnect).

```bash
# No 401-after-an-hour: refresh is automatic behind every command
nylas email list --json --limit 10

# If a call ever fails, this tells you which problem it is
nylas auth status        # healthy = refresh working; needs re-auth = reconnect
nylas auth login --provider google   # only needed if the refresh token is dead
```

## Next steps

- [Refresh token management](https://cli.nylas.com/guides/refresh-token-management) — how the refresh flow works
- [Fix the invalid_grant error](https://cli.nylas.com/guides/fix-invalid-grant-error) — the dead-refresh-token case
- [Gmail API error codes](https://cli.nylas.com/guides/gmail-api-error-codes) — the 401 alongside other codes
- [Monitor integration health](https://cli.nylas.com/guides/monitor-email-integration-health-cli) — catch dead grants early
- [Full command reference](https://cli.nylas.com/docs/commands) — every flag and subcommand documented
