
Step by Step Guide to solve n8n Invalid Credentials Error
Who this is for: DevOps engineers, system administrators, and n8n power users who manage self‑hosted n8n instances and need a reliable way to resolve login failures. We cover this in detail in the n8n Authentication Errors Guide.
I’ve debugged this error at 2am more times than I’d like to admit. The workflow was running fine in staging, deployed to production, and suddenly every credential shows “Invalid credentials” – nothing changed, same env vars, same database. After hours of head-scratching the culprit was a single trailing newline in the .env file. Most devs get stuck here because the error message is completely generic – it looks the same whether your bcrypt hash is corrupt, your OAuth token expired, or your encryption key rotated. This guide cuts through all of it.
Which Error Do You Have? (Go Straight to the Fix)
Don’t read the whole post. Find your exact error message below and jump to the fix.
| Your exact error message | Most likely cause | Jump to fix |
|---|---|---|
Invalid credentials on login screen |
bcrypt hash mismatch or hidden whitespace in env var | Section 2 → Basic Auth |
Credentials could not be decrypted |
N8N_ENCRYPTION_KEY changed or lost after update/redeploy | Section 2.4 → Encryption Key |
03000064:digital envelope routines::bad decrypt |
Node.js version mismatch or corrupted encryption key | Section 2.4 → Encryption Key |
invalid_grant after OAuth redirect |
Expired OAuth refresh token (Google rotates after 6 months) | Section 2.2 → OAuth |
Redirect URI mismatch |
N8N_OAUTH_CALLBACK_URL doesn’t match provider settings | Section 2.2 → OAuth |
401 Unauthorized inside a workflow node |
Revoked API key, wrong key type, or hidden character in value | Section 2.3 → API Key |
403 Forbidden on specific operations |
Missing OAuth scopes — you authorized with fewer permissions than needed | Section 2.2 → OAuth scopes |
Correct password, still rejected, even after n8n reset |
Container not restarted after reset — this is the #1 missed step | Section 5 → Admin Reset |
Quick Diagnosis
- Stop the n8n service/container.
- Verify the exact values of
N8N_BASIC_AUTH_USERandN8N_BASIC_AUTH_PASSWORD(or the OAuth variables) in your.env, Docker‑Compose, or Kubernetes manifest. - If the password was changed recently, clear the stored hash:
UPDATE "User" SET "passwordHash" = NULL WHERE "email" = '<your-email>';
- Restart n8n and log in with the updated credentials.
If the issue persists, follow the detailed troubleshooting steps below.
1. What Triggers the “Invalid credentials” Message?
If you encounter any token expired error resolve them before continuing with the setup.
| Trigger | Where It Happens | Typical Symptom |
|---|---|---|
| Basic Auth mismatch | src/Executors/BasicAuth (Node.js) | Login form rejects correct username/password |
| OAuth provider token error | src/Executors/OAuth2 | “Invalid credentials” after redirect |
| API key not found | src/Executors/ApiKey | 401 response with same message |
| Corrupted DB hash | PostgreSQL / SQLite User table |
Even correct env vars fail |
The error is thrown after n8n validates the supplied secret against the stored bcrypt hash. If the hash is missing, outdated, or generated with a different salt, the generic Invalid credentials response is returned.
2. Verify Your Authentication Method
If you encounter any api key not recognized resolve them before continuing with the setup.
2.1 Basic Authentication (most common)
Micro‑summary: Ensure the environment variables match the user record in the database and contain no hidden characters.
- Locate the variables – they are defined in one of the following:
- Docker‑Compose
environment:block - Kubernetes secret
env:section .envfile for a localnpm run start
- Docker‑Compose
- Check for invisible whitespace – a trailing newline or space will break bcrypt comparison.
# Show hidden characters in the password variable echo -n "$N8N_BASIC_AUTH_PASSWORD" | od -c
- Confirm the DB entry matches – query the
Usertable:SELECT "email", "passwordHash" FROM "User" WHERE "email" = 'admin@example.com';
emailmust equalN8N_BASIC_AUTH_USER.passwordHashmust be a valid bcrypt string ($2b$…).
What the logs actually look like when this fires — enable debug mode and look for this pattern:
export N8N_LOG_LEVEL=debug docker logs -f n8n 2>&1 | grep -A3 "Invalid credentials" # Output you'll see: [2026-01-15 02:14:33.821] [debug] User lookup query: SELECT * FROM "User" WHERE email = 'admin@example.com' [2026-01-15 02:14:33.824] [debug] bcrypt.compare() returned: false [2026-01-15 02:14:33.825] [warn] Invalid credentials for user: admin@example.com
If you see bcrypt.compare() returned: false, the password variable has a mismatch with the stored hash — invisible character or wrong value. If you see a DB error before the Invalid credentials line, the problem is database connectivity, not the credential itself.
2.2 OAuth2 / OpenID Connect
| Variable | Description |
|---|---|
| N8N_OAUTH_CLIENT_ID | Client ID from the identity provider |
| N8N_OAUTH_CLIENT_SECRET | Secret (URL‑encode special characters) |
| N8N_OAUTH_CALLBACK_URL | Exact callback URL registered with the provider |
A mismatch in any of these values causes the provider to reject the token exchange, which n8n surfaces as Invalid credentials.
OAuth token expiry — the silent killer. Most devs get stuck here because the workflow runs fine for weeks, then suddenly breaks with no code changes. Here’s exactly when each provider expires your tokens:
| Provider | Access token lifetime | Refresh token expires when | Fix |
|---|---|---|---|
| Google (Sheets, Gmail, Drive) | 1 hour | 6 months of inactivity, or 7 days if app is in “testing” mode | Reconnect credential; submit app for verification |
| Slack | Never (unless revoked) | On workspace app reinstall or admin revocation | Check Slack App Management → Installed Apps |
| HubSpot | 6 hours | On app scope changes or user removal | Match scopes in HubSpot app settings exactly |
| Microsoft (365, Teams) | 1 hour | 90 days of inactivity (configurable by admin) | Reconnect; check Azure AD token policy |
Common OAuth scope mismatches that cause 403 errors (the error message says “Invalid credentials” but the real problem is missing permissions):
| Service | Missing scope | What breaks |
|---|---|---|
| Google Sheets | spreadsheets (not spreadsheets.readonly) |
Can read but cannot write |
| Gmail | gmail.send |
Sending emails fails silently |
| Slack | chat:write |
Posting messages returns 403 |
| HubSpot | crm.objects.contacts.write |
Contact creates fail; reads work fine |
2.3 API Key Authentication
Key name is defined by N8N_API_KEY (or a custom header). Verify that the key stored in the ApiKey table matches the environment variable.
Wrong API key type is the most common cause of instant 401s. Each service has multiple key types and n8n needs a specific one:
| Service | Correct key type for n8n | Common mistake |
|---|---|---|
| Stripe | Secret key — starts with sk_live_ or sk_test_ |
Using publishable key (pk_) instead |
| OpenAI | API key — starts with sk- (project or org key) |
Using a project key when org key is required, or vice versa |
| HubSpot | Private App access token (not the old API key) | HubSpot deprecated legacy API keys in 2022 — old keys fail silently |
| SendGrid | Full Access API key (not Restricted) | Restricted key missing mail.send permission |
| Twilio | Account SID + Auth Token (both required) | Using API Key SID instead of Account SID |
Detect hidden characters in a pasted API key — copy-paste introduces invisible characters far more often than you’d expect:
# Check for trailing spaces or newlines in your API key variable
echo -n "$YOUR_API_KEY" | wc -c # Should match exact key length from dashboard
echo -n "$YOUR_API_KEY" | od -c # Look for \n or spaces at start/end
# If the key is in a Function node, paste this temporarily to inspect it:
const key = $credentials.apiKey;
console.log('Length:', key.length);
console.log('Hex:', Buffer.from(key).toString('hex'));
// Any 0a = newline, 20 = space, 0d = carriage return at start/end = culprit
2.4 Encryption Key Errors – “Credentials could not be decrypted”
This is the most common error after an n8n upgrade or Docker redeploy. It is a different problem from “Invalid credentials” at login — the login works fine, but workflow credentials (API keys, OAuth tokens) are unreadable.
What the error looks like in logs:
Error: Credentials could not be decrypted. The likely reason is that a different 'encryptionKey' was used to encrypt the data.Or:
03000064:digital envelope routines::bad decrypt
Root cause: n8n encrypts all stored credentials with N8N_ENCRYPTION_KEY. If this key changes between deployments — even a new Docker container without the key explicitly set — n8n generates a new random key and can no longer read existing encrypted data.
If → Then decision:
| Situation | What to do |
|---|---|
You never set N8N_ENCRYPTION_KEY explicitly |
Find the auto-generated key in /home/node/.n8n/config and set it as the env var permanently |
| You updated n8n version and the error appeared | Verify the encryption key in your compose file matches what was used before — check git history or backup |
| You migrated to a new server/container | Copy the original N8N_ENCRYPTION_KEY value to the new environment — it must be identical |
| Key is correct but error persists | Check for special characters — some shells misread $, =, or ! in the key value. Wrap in single quotes |
| Queue mode (multiple workers) | Every worker must have the identical N8N_ENCRYPTION_KEY — one mismatched worker silently breaks credentials |
Recover the auto-generated key:
# If n8n generated the key automatically, find it here: docker exec -it n8n cat /home/node/.n8n/config | grep encryptionKey # Then set it permanently in your docker-compose.yml: environment: - N8N_ENCRYPTION_KEY=the-key-you-found-above # Never let n8n auto-generate it again — always set it explicitly
3. Step‑by‑Step Debugging Checklist
| Step | Action |
|---|---|
| 1 | Stop n8n to avoid race conditions. |
| 2 | Export current env for audit: printenv | grep N8N_ > env_audit.txt |
| 3 | Validate env values for hidden characters: cat -A env_audit.txt |
| 4 | Inspect DB user record (PostgreSQL example): psql -d n8n -c "SELECT email, passwordHash FROM \"User\";" |
| 5 | Re‑hash a new password (if needed): node -e "console.log(require('bcrypt').hashSync('newPass',10))" |
| 6 | Update DB with the new hash: UPDATE "User" SET "passwordHash" = '<newHash>' WHERE "email" = '<user>'; |
| 7 | Clear cached session store (Redis example): redis-cli FLUSHALL |
| 8 | Restart n8n and test login. |
EEFA Note: In production, never log plaintext passwords. Store secrets in a vault (AWS Secrets Manager, HashiCorp Vault) and reference them via
${SECRET_NAME}in your container definition.
4. Common Pitfalls & How to Resolve Them?
| Pitfall | Fix |
|---|---|
Trailing newline in .env |
Remove the newline or wrap the value in quotes. |
Spaces in docker run -e |
Quote the entire argument: -e "N8N_BASIC_AUTH_PASSWORD=My P@ssw0rd" |
| Mismatched bcrypt version | Upgrade n8n to the latest LTS; hash formats are compatible. |
Empty passwordHash after DB restore |
Manually set a new hash (see Step 5) or run n8n reset. |
| OAuth redirect URI typo | Ensure the URL (including protocol, port, and path) matches both the provider and N8N_OAUTH_CALLBACK_URL. |
| API key stored in wrong table | Verify plugin documentation; ensure N8N_API_KEY matches the stored key. |
⚠ The #1 missed step:
n8n resetwithout a container restart does nothing.If you run
docker exec -it n8n n8n user-management:resetand it says “Successfully reset the database to default user state” — but the login page still rejects you — the fix is simple: restart the container. The reset modifies the DB, but n8n has to reinitialise to read the reset state. Run:docker exec -it n8n n8n user-management:reset docker restart n8n # Now open the browser — you'll see the fresh setup wizard
5. Deep Dive: Re‑creating the Admin User (When DB Hash Is Corrupt)
Micro‑summary: Use the built‑in n8n reset command to wipe the broken hash and generate a fresh one without affecting workflow data.
5.1 Stop n8n
docker compose down
5.2 Run a one‑off container to reset credentials
docker run --rm \ -e N8N_HOST=localhost \ -e N8N_BASIC_AUTH_USER=admin@example.com \ -e N8N_BASIC_AUTH_PASSWORD=SuperSecure123 \ -v n8n_data:/home/node/.n8n \ n8nio/n8n:latest \ n8n reset
5.3 Restart n8n
docker compose up -d
The n8n reset command clears the existing admin hash and writes a new bcrypt hash using the supplied environment variables. All workflow JSON remains intact because it resides in the Workflow table, not the User table.
EEFA Warning: Run
n8n resetonly in environments where you control access. In multi‑user setups, coordinate with the team to avoid accidental lock‑outs.
Running SQLite (not PostgreSQL)? The reset command works the same way. If it fails, you can also directly update the SQLite database:
# Install sqlite3 if needed apt-get install -y sqlite3 # Find your database file find / -name "database.sqlite" 2>/dev/null # Manually set a new bcrypt hash (generate hash first with node command above) sqlite3 /home/node/.n8n/database.sqlite \ "UPDATE user SET passwordHash='$2b$10$newHashHere' WHERE email='admin@example.com';"
6. Logging & Monitoring for Future Issues
- Enable debug logs (temporarily) to capture credential validation details:
export N8N_LOG_LEVEL=debug
- Watch the logs while reproducing the error:
docker logs -f n8n
Look for lines containing
Invalid credentialsand note the precedingUserlookup query. - Set up an alert on the log pattern using Loki/Promtail, CloudWatch Metric Filters, or a similar service to catch the error before users report it.
7. Production‑Grade Checklist
- ✅ Secrets stored in a vault, not in plain
.envfiles. - ✅
N8N_BASIC_AUTH_PASSWORDmeets minimum entropy (≥12 characters, mixed case, symbols). - ✅ Database backups include the
Usertable; test admin‑credential restore quarterly. - ✅ Logging level set to
infoin production; enabledebugonly during incidents. - ✅ Health‑check endpoint (
/healthz) monitors DB connectivity and authentication service status. - ✅
N8N_ENCRYPTION_KEYis set explicitly and stored in a secret manager — never auto-generated. - ✅ In queue mode: verify all workers share the same
N8N_ENCRYPTION_KEYvalue. - ✅ OAuth credentials tested after 6 months of inactivity to catch silent token expiry.
Frequently Asked Questions:
Why does n8n show “Invalid credentials” even when my password is correct?
The most common cause is a hidden whitespace character — a trailing space or newline — in the environment variable value. Run echo -n "$N8N_BASIC_AUTH_PASSWORD" | od -c to reveal it. The second most common cause is a corrupt bcrypt hash in the User table from a failed database migration or restore. Use n8n user-management:reset followed by a container restart to fix it.
What does “Credentials could not be decrypted” mean in n8n?
This error means the N8N_ENCRYPTION_KEY used to encrypt stored workflow credentials no longer matches. This usually happens after a Docker update, container redeploy, or server migration where the original key was not preserved. Find the original key in /home/node/.n8n/config and set it explicitly as an environment variable — it must be identical across all n8n instances.
How do I reset the n8n admin password in Docker?
Run docker exec -it n8n n8n user-management:reset, then immediately run docker restart n8n. The restart is mandatory — without it the reset does not take effect. After restarting, the browser will show the initial setup wizard where you create new admin credentials.
Why does n8n show “invalid_grant” for Google credentials?
Google OAuth refresh tokens expire after 6 months of inactivity, or after 7 days if your OAuth app is still in “testing” mode. Go to n8n Credentials, select the Google credential, and click Reconnect to re-authorise. To prevent recurrence, submit your Google OAuth app for verification or ensure at least one workflow using it runs every 5 months.
Will running n8n reset delete my workflows?
No. The n8n reset command only clears the admin user record in the User table. All workflow JSON is stored in the Workflow table and is untouched. Your credentials (API keys, OAuth tokens) stored in the Credentials table are also untouched — they remain encrypted but accessible once you log back in.
n8n credentials work in test mode but fail in production — why?
This is almost always an environment mismatch. You are likely using test/sandbox API keys (e.g. sk_test_ for Stripe) in production, or your OAuth app is in “testing” mode with short-lived tokens. Create separate credentials in n8n labeled “Production” using live keys, and switch workflow nodes to use those credentials before going live.
Conclusion
The “Invalid credentials” error in n8n almost always stems from a mismatch between environment variables and the stored bcrypt hash, or from malformed OAuth/API‑key configurations. By systematically stopping the service, auditing secrets, verifying the database record, and, if necessary, resetting the admin user, you can restore access without losing workflow data. Implementing the production checklist — vault‑backed secrets, a permanently set encryption key, regular backups, and targeted logging — prevents recurrence and ensures a resilient, secure n8n deployment.



