NeahNew/N8N_API_KEY_MISMATCH_FIX.md
2026-01-09 11:19:32 +01:00

6.4 KiB

N8N API Key Mismatch - 401 Unauthorized

🔍 Problem Identified

Error: 401 - "Unauthorized"
Log: Invalid API key { received: 'present', expected: 'configured' }

Status:

  • Endpoint is being called (Mission Created Webhook Received)
  • API key is being sent (received: 'present')
  • API key values don't match

🔍 Root Cause

The API key sent by N8N in the x-api-key header does not match the N8N_API_KEY environment variable on the server.

How It Works

  1. Server sends to N8N (line 420 in app/api/missions/route.ts):

    config: {
      N8N_API_KEY: process.env.N8N_API_KEY,  // From server environment
      MISSION_API_URL: process.env.NEXT_PUBLIC_API_URL
    }
    
  2. N8N uses this value in "Save Mission To API" node:

    x-api-key: {{ $node['Process Mission Data'].json.config.N8N_API_KEY }}
    
  3. Server receives and validates (line 42 in app/api/missions/mission-created/route.ts):

    if (apiKey !== expectedApiKey) {
      // Keys don't match → 401 error
    }
    

The Problem

If process.env.N8N_API_KEY is undefined or empty when sending to N8N:

  • N8N receives undefined or empty string
  • N8N sends empty string in header
  • Server expects the actual key value
  • Keys don't match → 401 error

Solution

Step 1: Verify N8N_API_KEY is Set

Check your environment variables:

# In your terminal (if running locally)
echo $N8N_API_KEY

# Or check in your application
# Create a test endpoint to verify

Expected: Should show the actual API key value (not empty)

Step 2: Ensure Same Key in Both Places

The key must be the same in:

  1. Server environment variable: N8N_API_KEY=your-key-here
  2. N8N workflow config: The value sent in config.N8N_API_KEY

If they're different, they won't match!

Step 3: Check What N8N is Sending

In N8N workflow "Save Mission To API" node, verify:

  1. Header x-api-key value:

    {{ $node['Process Mission Data'].json.config.N8N_API_KEY }}
    
  2. What this resolves to:

    • If config.N8N_API_KEY is undefined → N8N sends empty string
    • If config.N8N_API_KEY has a value → N8N sends that value
  3. Check N8N execution logs:

    • Look at the actual request being sent
    • Check the x-api-key header value
    • Compare with your server's N8N_API_KEY

Step 4: Fix the Mismatch

Option A: If server's N8N_API_KEY is undefined

Add to .env.local (or production environment):

N8N_API_KEY=LwgeE1ntADD20OuWC88S3pR0EaO7FtO4

Restart the application.

Option B: If N8N is sending wrong value

Check what value N8N has in config.N8N_API_KEY:

  • It should match the server's N8N_API_KEY
  • If different, update one to match the other

Option C: Hardcode in N8N (not recommended)

If you can't sync the values, you could hardcode in N8N:

x-api-key: LwgeE1ntADD20OuWC88S3pR0EaO7FtO4

But this is less secure - better to use environment variable.


🧪 Testing

Test 1: Check Server Environment

Create test endpoint:

// app/api/test-n8n-key/route.ts
import { NextResponse } from 'next/server';

export async function GET() {
  return NextResponse.json({
    hasN8NApiKey: !!process.env.N8N_API_KEY,
    keyLength: process.env.N8N_API_KEY?.length || 0,
    keyPrefix: process.env.N8N_API_KEY ? process.env.N8N_API_KEY.substring(0, 4) + '...' : 'none'
  });
}

Visit: http://localhost:3000/api/test-n8n-key

Expected:

{
  "hasN8NApiKey": true,
  "keyLength": 32,
  "keyPrefix": "Lwge..."
}

Test 2: Check What N8N Sends

In N8N execution logs, check the "Save Mission To API" node:

  • Look at the request headers
  • Find x-api-key header
  • Note the value

Compare with server's N8N_API_KEY - they must match exactly.

Test 3: Manual Test

Test the endpoint with the correct key:

curl -X POST https://hub.slm-lab.net/api/missions/mission-created \
  -H "Content-Type: application/json" \
  -H "x-api-key: LwgeE1ntADD20OuWC88S3pR0EaO7FtO4" \
  -d '{
    "missionId": "test-id",
    "name": "Test",
    "creatorId": "user-id"
  }'

Expected: 200 OK (if mission exists) or 404 (if mission doesn't exist)

If 401: The key in the curl command doesn't match server's N8N_API_KEY


🔧 Common Issues

Issue 1: Key is undefined when sending to N8N

Symptom: N8N receives undefined or empty string in config.N8N_API_KEY

Cause: process.env.N8N_API_KEY is not set when creating mission

Fix: Add N8N_API_KEY to environment and restart

Issue 2: Different keys in different environments

Symptom: Works in development but not production (or vice versa)

Cause: Different N8N_API_KEY values in different environments

Fix: Use the same key in all environments, or update N8N to use environment-specific keys

Issue 3: Key has extra spaces or characters

Symptom: Keys look the same but don't match

Cause: Extra spaces, newlines, or special characters

Fix:

# Correct
N8N_API_KEY=LwgeE1ntADD20OuWC88S3pR0EaO7FtO4

# Wrong (with quotes)
N8N_API_KEY="LwgeE1ntADD20OuWC88S3pR0EaO7FtO4"

# Wrong (with spaces)
N8N_API_KEY = LwgeE1ntADD20OuWC88S3pR0EaO7FtO4

📋 Debugging Checklist

  • N8N_API_KEY is set in server environment
  • Key value matches what N8N is sending
  • No extra spaces or characters in key
  • Server has been restarted after adding key
  • Test endpoint shows key is loaded
  • N8N execution logs show correct key in header
  • Manual curl test works with the key

🎯 Expected Flow After Fix

  1. Mission created
  2. N8N workflow triggered
  3. Server sends config.N8N_API_KEY to N8N
  4. N8N creates integrations
  5. N8N calls /api/missions/mission-created
  6. N8N sends x-api-key header with same value
  7. Server validates key matches
  8. IDs saved to database

📝 Summary

Problem: 401 Unauthorized - API key mismatch

Root Cause: The API key sent by N8N doesn't match the server's N8N_API_KEY

Solution:

  1. Ensure N8N_API_KEY is set in server environment
  2. Ensure N8N uses the same key value
  3. Verify keys match exactly (no spaces, same value)

After Fix: The endpoint should return 200 OK and save integration IDs.


Document Created: $(date) Priority: CRITICAL - Blocks integration IDs from being saved