n8n Token Expired Error: Complete Fix Guide (Google, Microsoft, Slack)

n8n token expired error fix guide

Step by Step Guide to solve n8n Token Expired Error

 


 

Who this is for: n8n users who have OAuth2‑protected workflows that suddenly stop with a “token expired” error — including the exact messages invalid_grant: Token has been expired or revoked, The access token is invalid or has expired, and Error: Request failed with status code 401. We cover this in detail in the n8n Authentication Errors Guide.


Quick Diagnosis

  1. Open the failing credential → OAuth2 tab.
  2. Enable Refresh Token (or add a refresh‑token URL).
  3. Click Refresh or run a one‑time HTTP Request node to exchange the refresh token for a new access token.
  4. Save the credential; the workflow runs again without the “Token expired” error.

Quick one‑liner for search results:
In n8n, enable the OAuth2 “Refresh Token” option or manually call the provider’s token endpoint to obtain a new access token; then re‑save the credential to resolve the “token expired” authentication error.


1. What “Token Expired” Means in n8n?

If you encounter any invalid credentials error resolve them before continuing with the setup.

Purpose – Clarify the two token types and why n8n stops a workflow.

Aspect Explanation
Access token Short‑lived (usually 1 h) string that authorises API calls.
Refresh token Long‑lived secret that can be exchanged for a new access token without user interaction.
n8n behaviour On a 401 Unauthorized response that contains *token expired* (or similar), n8n marks the credential as stale and halts the workflow.
Root cause The provider’s access token has reached its TTL; no valid refresh token is configured or the refresh flow failed.

Note – Some providers (e.g., Microsoft Graph) rotate refresh tokens on each use. Let n8n manage the rotation automatically instead of storing a static token.


1a. Exact Error Messages This Guide Fixes

If you landed here by pasting an error message into Google, here’s a map of every known variant to the section that fixes it:

Exact error string you see in n8n Root cause Go to section
The access token is invalid or has expired Access token TTL reached; no valid refresh token Section 3 (Auto-Refresh)
invalid_grant: Token has been expired or revoked Refresh token itself was revoked by the provider Section 6 (invalid_grant fix) + Section 9
Error: Request failed with status code 401 Generic expired token — provider returned 401 Section 2, Section 3
dummy.stack.replace (Microsoft Outlook) n8n internal parsing bug on Microsoft token errors Section 5b (Microsoft fix)
Token expires every 7 days (Google) App in Testing mode — 7-day token limit enforced Section 5a (Google 7-day fix)
Error: Request failed with status code 403 on token refresh Provider returns 403 instead of 401 — n8n never auto-refreshes Section 5c (403 bug)

2. Spotting the Error in n8n

If you encounter any api key not recognized resolve them before continuing with the setup.

Purpose – Show where the problem appears in the UI and logs.

  • Execution log – Look for Error: Request failed with status code 401 and a message containing “token expired”, “invalid_token”, or “expired_token”.
  • Credential status badge – Expired tokens display a red exclamation icon in the Credentials list.
  • Workflow pause – The offending node turns red and the workflow stops at that step.

Tip – Enable Error Workflow in production to capture token‑expiry events and route them to a remediation sub‑workflow.


3. n8n’s Built‑In OAuth2 Refresh Mechanism

Purpose – Walk through the UI steps to let n8n auto‑refresh tokens.

  1. Open the credential (e.g., Google OAuth2 API).
  2. In the OAuth2 tab, fill these fields:
Field Typical value
Access Token URL https://oauth2.googleapis.com/token
Refresh Token URL Same as Access Token URL for most providers
Client ID / Secret Your app’s credentials
Scope https://www.googleapis.com/auth/drive
Use Refresh Token ON
Auto‑Refresh Enabled (default)
  1. Click Refresh – n8n calls the refresh endpoint, stores the new access token, and updates the credential.

Note – If the provider returns a new refresh token, n8n overwrites the stored one automatically. Do not edit the refresh token field manually.


4. Manual Refresh with an HTTP Request Node

Purpose – Provide a fallback when the UI cannot refresh (custom OAuth2 flows).

4.1. Define the HTTP request (URL, method, headers)

{
  "url": "https://oauth2.provider.com/token",
  "method": "POST",
  "headerParametersUi": {
    "parameter": [
      {
        "name": "Content-Type",
        "value": "application/x-www-form-urlencoded"
      }
    ]
  }
}

4.2. Add the body parameters required for a refresh

{
  "bodyParametersUi": {
    "parameter": [
      { "name": "grant_type", "value": "refresh_token" },
      { "name": "refresh_token", "value": "{{$json[\"refresh_token\"]}}" },
      { "name": "client_id", "value": "YOUR_CLIENT_ID" },
      { "name": "client_secret", "value": "YOUR_CLIENT_SECRET" }
    ]
  },
  "jsonParameters": false
}

Combine the two snippets in a single HTTP Request node, run it once, and store the returned access_token back into the credential (via a Set node or the Credential Store API).

Warning – Never log client_secret or refresh_token in production logs. Use n8n’s secret management (environment variables) instead.


5. Automating Token Renewal – Best‑Practice Configuration

Purpose – Show a concise checklist for reliable, hands‑off token management.

Step Action Why it matters
1️⃣ Enable “Auto‑Refresh” in the credential UI n8n silently swaps tokens before they expire (default 5 min buffer).
2️⃣ Set “Token Expiry Buffer” to 300 seconds (if available) Guarantees a fresh token even under clock skew.
3️⃣ Store credentials in a dedicated environment variable (e.g., CREDENTIALS_GOOGLE_OAUTH) Isolates secrets from workflow data.
4️⃣ Add a “Token Watchdog” sub‑workflow that listens for 401 errors and triggers a manual refresh node as a fallback Handles edge cases where the provider revokes the refresh token.
5️⃣ Log token refresh events to a monitoring system (Loki, Datadog, etc.) Provides an audit trail and early detection of abnormal revocations.

5a. Google OAuth2 Token Expires Every 7 Days: The Fix

This is the most reported token issue in the entire n8n community in 2025–26. If your Google-connected workflow (Gmail, Google Sheets, Google Drive) runs fine for a week then suddenly breaks with invalid_grant – your Google OAuth app is still in Testing mode.

Google enforces a hard 7-day token expiry for apps in Testing mode. After 7 days, the refresh token is automatically invalidated, and no amount of clicking Refresh in n8n will fix it – because the refresh token itself is dead.

Permanent fixes (pick one):

  1. Publish your Google OAuth app — Go to Google Cloud Console → OAuth consent screen → Publishing status → change from Testing to In production. This removes the 7-day limit. You don’t need to submit for verification unless you’re using sensitive scopes.
  2. Use a Google Service Account instead — Service Accounts never expire and don’t require user consent. Ideal for server-to-server workflows (Sheets, Drive, BigQuery). In n8n, create a Service Account credential, download the JSON key, and paste it into the credential. No refresh tokens involved at all.
  3. Re-authorise every 7 days (temporary workaround) — If you can’t publish the app, set a calendar reminder to re-authenticate weekly. Not recommended for production.

Note: Adding test users to your Google OAuth app does NOT remove the 7-day limit. Only publishing the app or switching to a Service Account solves it permanently.


5b. Microsoft OAuth2 Token Expired in n8n (Outlook, Teams, SharePoint)

Microsoft uses a different token lifecycle from Google. Here’s what you need to know:

Token type Lifespan What happens in n8n
Access token ~1 hour Auto-refreshed by n8n if refresh token is valid
Refresh token (consumer accounts) 90 days (rolling) Stays alive as long as workflows run at least once in 90 days
Refresh token (work/school accounts) Controlled by Azure AD policy (often 14 days inactive) Breaks if workflow is paused for 2+ weeks

The dummy.stack.replace error — This cryptic error appears in n8n when Microsoft returns a token-related error but n8n’s internal error parser fails to format it correctly. It is NOT a code bug in your workflow. Fix it by:

  1. Deleting the Microsoft credential in n8n.
  2. Re-creating it and going through the OAuth consent flow again.
  3. Making sure the Microsoft app registration has offline_access in its API permissions (this grants the refresh token).

For work/school accounts — If your organisation’s Azure AD policy sets a short refresh token lifetime, you cannot override it from n8n. Contact your IT admin to adjust the token lifetime policy, or switch to a Service Principal (the Microsoft equivalent of a Service Account) with a client secret or certificate — these don’t expire on inactivity.


5c. The 403 Token Refresh Bug – When n8n Never Auto-Refreshes

This is a gap that no competitor covers — and it affects a growing number of integrations.

n8n’s auto-refresh mechanism is triggered when the API returns a 401 Unauthorized response. The assumption is: 401 = expired token → try refresh. But some APIs return 403 Forbidden when a token expires instead of 401. Examples include Microsoft Fabric, Avito, and certain enterprise APIs with custom auth layers.

When this happens, n8n sees a 403, does NOT attempt a refresh (because it only watches for 401), and the workflow fails permanently — even if a perfectly valid refresh token is sitting in the credential.

How to fix the 403 refresh bug:

  1. Add an Error branch on the failing node — Connect an Error output to an IF node. Check if {{ $json.error.status }} equals 403 AND the error message contains token or expired.
  2. Trigger a manual refresh via HTTP Request node — Use the flow from Section 4 to force a token refresh when the 403 is caught.
  3. Re-execute the original node — After the refresh succeeds, use an Execute Workflow node to re-trigger the failed workflow from the top.
// IF node condition to catch 403 token expiry
{{ $json.error.status === 403 && $json.error.message.includes("token") }}

Note: This 403 vs 401 mismatch is an open issue in n8n’s GitHub (issue #18517, August 2025). Until it is patched natively, the manual Error branch workaround above is the only reliable fix.


5d. Slack Token Expired in n8n

Slack’s token model is different from Google and Microsoft. Most Slack tokens are long-lived bot tokens that do not expire on a schedule. If you’re seeing a token expired error with Slack in n8n, the cause is almost always one of these:

  • The Slack app was uninstalled and reinstalled — this invalidates all previous tokens. Re-authenticate the credential in n8n.
  • A workspace admin revoked the token — check the Slack admin panel under Installed Apps → your app → Permissions.
  • Token rotation was enabled on the Slack app — if you deliberately enabled token rotation in the Slack app manifest, you need to handle the rotation event and update the credential in n8n. Most users should leave rotation disabled.

5e. Salesforce Token Expired in n8n

Salesforce access tokens expire after a session timeout set by your org (default is typically 2 hours, but admins can set it as low as 15 minutes). Refresh tokens in Salesforce are long-lived but subject to Connected App policies.

  • If refresh keeps failing: check the Connected App’s OAuth policies in Salesforce Setup. “Refresh Token Policy” may be set to expire after a fixed time or after inactivity.
  • Excessive refresh attempts can lock the client: Salesforce rate-limits refresh calls. If n8n retries too aggressively, the client gets blocked. Add a wait/delay node before retrying.
  • For production: use a Salesforce Connected App with a certificate-based auth flow instead of user-password OAuth. This gives you a non-expiring session.

6. Common Pitfalls & Fixes

Purpose – Highlight frequent mistakes and their fixes.

Pitfall Symptom Fix
Static access token used Works once, then fails after 1 h Switch to OAuth2 credential with refresh token enabled.
Missing refresh_token in credential “Token expired” persists after clicking Refresh Re‑authorise the OAuth flow with access_type=offline to obtain a refresh token.
Clock skew on the n8n server Token considered expired early Sync server time via NTP; increase expiry buffer.
Provider revoked refresh token Refresh request returns invalid_grant Re‑authenticate the user (run the OAuth consent screen again).
Using a personal access token (PAT) with no refresh No auto‑renewal possible Switch to OAuth2 flow or schedule a script to generate a new PAT before expiry.

6a. Deep Dive: Fixing invalid_grant in n8n

invalid_grant is the most confusing token error because it looks like a token expiry but the fix is completely different from a normal expiry. It means the refresh token itself is dead — not just the access token. Clicking Refresh in n8n will not help.

Reasons a refresh token becomes invalid_grant:

  • The user revoked access in the provider’s security settings (e.g., Google Account → Third-party apps → removed n8n).
  • The OAuth app is in Google Testing mode and the 7-day limit was hit (see Section 5a).
  • The user changed their account password — some providers invalidate all refresh tokens on password change.
  • The OAuth app’s client secret was rotated — the old refresh token is now linked to a dead secret.
  • The credential was unused for longer than the provider’s inactivity limit (Microsoft: 90 days, Google: 6 months).

The only fix for invalid_grant:

  1. Delete the current credential in n8n (or click Reconnect).
  2. Go through the full OAuth consent flow again — the user must log in and approve access.
  3. If using Google and this keeps happening every 7 days, fix the root cause in Section 5a first.

Note – Test the refresh endpoint with curl outside n8n before re-authenticating. If curl also returns invalid_grant, the problem is confirmed to be at the provider level, not an n8n bug.


6b. Token Health Monitor – Self-Healing Workflow

Instead of waiting for a workflow to fail at 2 AM and scrambling to fix it manually, you can build a proactive Token Health Monitor in n8n that checks and refreshes credentials on a schedule before they expire.

How to build it:

  1. Schedule Trigger node — Set to run every 6 hours (or every hour for critical workflows).
  2. HTTP Request node (Token Check) — Make a lightweight API call to the provider (e.g., a profile endpoint or token introspection endpoint). This call uses the credential you want to monitor.
  3. IF node — Check the response status code. If 200 → token is healthy, end. If 401 or 403 → token needs refresh.
  4. HTTP Request node (Force Refresh) — Use the manual refresh flow from Section 4 to get a new access token.
  5. Set node — Write the new token back to the credential store.
  6. Slack / email notification node — Alert your team if the refresh also fails (i.e., invalid_grant — requires human re-authentication).
// IF node: route based on token health check response
{{ $json.statusCode === 401 || $json.statusCode === 403 }}
// → true branch = refresh needed
// → false branch = token healthy, do nothing

Pro tip – For Google Service Accounts, skip the health monitor. Service Account tokens are generated fresh per-request and cannot expire mid-session. Reserve the health monitor pattern for user OAuth2 credentials.


7. Troubleshooting Checklist

CheckList Verify the credential’s Refresh Token field is populated.
Confirm the Access Token URL and Refresh Token URL match the provider’s documentation.
Check the server’s system clock (date -u).
Inspect the Execution Log for the exact error payload (error_description).
For custom OAuth2, ensure grant_type=refresh_token is sent.
Test the refresh endpoint with curl outside n8n to rule out provider‑side issues.
Review recent changes to scopes or client secret that may have invalidated the token.
If error is invalid_grant — do NOT click Refresh. Delete the credential and re-authenticate (see Section 6a).
If Google token expires every 7 days — publish your OAuth app or switch to a Service Account (see Section 5a).
If error is 403 (not 401) — n8n won’t auto-refresh. Build the Error branch workaround from Section 5c.
If all else fails, delete and recreate the credential (re‑authorise).

8. Real‑World Example – Refreshing a Google Drive Token

Purpose – Demonstrate the end‑to‑end flow for a common provider.

8.1. UI steps

  1. Create a Google OAuth2 credential (if missing).
  2. Set Scope to https://www.googleapis.com/auth/drive.
  3. Enable Use Refresh Token → Auto‑Refresh.
  4. Save and click Refresh.

8.2. Manual curl fallback (if UI fails)

curl -X POST \
  -d "client_id=YOUR_CLIENT_ID" \
  -d "client_secret=YOUR_CLIENT_SECRET" \
  -d "refresh_token=YOUR_REFRESH_TOKEN" \
  -d "grant_type=refresh_token" \
  https://oauth2.googleapis.com/token

Sample response:

{
  "access_token": "ya29.a0AfH6SM...",
  "expires_in": 3599,
  "scope": "https://www.googleapis.com/auth/drive",
  "token_type": "Bearer"
}

Copy the access_token into the credential (or let n8n store it automatically).

Tip – Google may return a new refresh token after a revocation. Capture and replace the stored refresh token immediately. If you skip this and the old refresh token was already invalidated, the next refresh will fail with invalid_grant.

8.3. Permanent fix: Use a Google Service Account

If you are tired of managing OAuth token expiry for Google integrations, switch to a Service Account. This is the recommended approach for any server-to-server workflow that doesn’t require user-specific access.

  1. Go to Google Cloud Console → IAM & Admin → Service Accounts → Create Service Account.
  2. Grant the Service Account the necessary role (e.g., Editor on the specific Google Sheet or Drive folder).
  3. Create a JSON key and download it.
  4. In n8n, create a new Google credential → select Service Account type → paste the JSON key content.
  5. Share the specific Google resource (Sheet, Drive folder, etc.) with the Service Account email address.

Service Account credentials in n8n never show a “token expired” error — the token is generated fresh on every API call using the private key, with no refresh token involved.


9. When to Re‑Create the Credential

Situation Recommended Action
Refresh request returns invalid_grant and the user can re‑authenticate Delete the credential, run the OAuth consent flow again.
Provider announces token policy change (new scopes, different endpoint) Re‑create the credential with updated settings.
Credential is shared across projects with differing scopes Split into separate credentials per project to avoid scope conflicts.
Google token keeps expiring every 7 days Publish your OAuth app first (Section 5a), then re-create the credential to get a fresh refresh token under the new policy.
Microsoft dummy.stack.replace error persists Delete and re-create the Microsoft credential; ensure offline_access scope is included (Section 5b).

Conclusion

Expired access tokens are a normal part of OAuth2’s security model. By ensuring Refresh Token is enabled, letting n8n’s Auto‑Refresh handle renewals, and adding a lightweight watchdog for edge cases, you can keep production workflows running without manual intervention. When the built‑in flow fails, a single‑use HTTP Request node or a curl call can recover the token instantly. For Google integrations, switching to a Service Account or publishing your OAuth app eliminates the token expiry problem at the root. For Microsoft, ensure offline_access is scoped and be aware of your organisation’s Azure AD token policies. Apply the checklist, monitor refresh events, and re‑authorise only when truly necessary to maintain a robust, production‑grade n8n environment.

Leave a Comment

Your email address will not be published. Required fields are marked *