# n8n Troubleshooting Guide

Common issues and solutions for n8n workflow debugging.

## Table of Contents
- [Authentication Errors](#authentication-errors)
- [Expression Errors](#expression-errors)
- [HTTP Request Errors](#http-request-errors)
- [Webhook Issues](#webhook-issues)
- [Data Transformation Problems](#data-transformation-problems)
- [Performance Issues](#performance-issues)
- [Execution Errors](#execution-errors)
- [Node-Specific Issues](#node-specific-issues)

## Authentication Errors

### 401 Unauthorized

**Symptoms:**
- HTTP Request node returns 401 status code
- Error message: "Unauthorized" or "Invalid credentials"

**Common Causes & Solutions:**

1. **Incorrect Credentials**
   - Check that the correct credential is selected in the node
   - Verify the credential contains the right API key/token
   - Re-create the credential if suspicious

2. **Expired Token**
   - OAuth2 tokens expire - reconnect the credential
   - API keys may have expiration dates - check provider dashboard
   - Refresh tokens if using OAuth2

3. **Wrong Authentication Method**
   - Verify API requires Bearer token, Basic Auth, or API Key
   - Check API documentation for correct header format
   - Common headers:
     - `Authorization: Bearer TOKEN`
     - `Authorization: Basic BASE64_CREDENTIALS`
     - `X-API-Key: YOUR_KEY`

4. **Missing Headers**
   ```javascript
   // Common required headers
   {
     "Authorization": "Bearer YOUR_TOKEN",
     "Content-Type": "application/json",
     "User-Agent": "n8n-workflow"
   }
   ```

5. **Incorrect Scope/Permissions**
   - OAuth2 credential may lack required scopes
   - API key may not have permission for the endpoint
   - Check provider's permission settings

**Debugging Steps:**
```bash
# Test authentication manually with curl
curl -H "Authorization: Bearer YOUR_TOKEN" \
     -H "Content-Type: application/json" \
     https://api.example.com/endpoint

# Check if token is valid
curl -H "Authorization: Bearer YOUR_TOKEN" \
     https://api.example.com/me
```

### 403 Forbidden

**Symptoms:**
- HTTP Request returns 403 status code
- "Access Denied" or "Forbidden" error

**Solutions:**
1. **Insufficient Permissions**
   - API key/token lacks permission for the resource
   - Check if account has access to the endpoint
   - Verify subscription/plan level

2. **IP Whitelist**
   - Some APIs require IP whitelisting
   - Add n8n server IP to allowed list
   - Check firewall rules

3. **Rate Limiting**
   - Too many requests in short time
   - Implement delays between requests
   - Use Split In Batches node with batch size limit

## Expression Errors

### "Cannot read property 'X' of undefined"

**Cause:** Trying to access a property that doesn't exist

**Solutions:**
```javascript
// Bad: Will fail if user is undefined
{{ $json.user.email }}

// Good: Use optional chaining
{{ $json.user?.email }}

// Good: Provide default value
{{ $json.user?.email ?? 'no-email@example.com' }}

// Good: Check existence first
{{ $json.user && $json.user.email ? $json.user.email : 'N/A' }}
```

### "Node not found"

**Cause:** Referenced node name doesn't match exactly

**Solutions:**
```javascript
// Bad: Wrong node name
{{ $node["Http Request"].json }}

// Good: Exact match (case-sensitive)
{{ $node["HTTP Request"].json }}

// Best: Use debug panel to verify exact node name
```

**Debugging:**
1. Check node name exactly as it appears in workflow
2. Node names are case-sensitive
3. Spaces and special characters must match exactly
4. Renamed nodes? Update all expressions

### Expression Syntax Errors

**Common Mistakes:**
```javascript
// Bad: Missing quotes around property names with dashes
{{ $json.user-name }}

// Good: Use bracket notation
{{ $json["user-name"] }}

// Bad: Trying to use expressions in Code node
const value = {{ $json.value }}; // Won't work!

// Good: In Code node, access directly
const value = items[0].json.value;

// Bad: Wrong quotation marks in expression
{{ $json.text === "value" }}

// Good: Use single quotes in expressions
{{ $json.text === 'value' }}
```

### DateTime Errors

**"Invalid DateTime"**
```javascript
// Bad: Invalid date format
{{ DateTime.fromISO($json.badDate) }}

// Good: Validate before parsing
{{ $json.date ? DateTime.fromISO($json.date).toISO() : '' }}

// Good: Handle invalid dates
{{ DateTime.fromISO($json.date).isValid ?
   DateTime.fromISO($json.date).toFormat('yyyy-MM-dd') :
   'Invalid Date' }}
```

## HTTP Request Errors

### 404 Not Found

**Solutions:**
1. **Verify URL**
   ```javascript
   // Check dynamic URLs evaluate correctly
   {{ `https://api.example.com/users/${$json.userId}` }}

   // Debug: Use Set node to see final URL
   // Set field "debug_url" to your URL expression
   ```

2. **Check API Endpoint**
   - Endpoint may have changed (check API docs)
   - Verify API version in URL
   - Check for typos in path

3. **Resource Doesn't Exist**
   - ID might be invalid
   - Resource might have been deleted
   - Test with known valid ID

### Timeout Errors

**"Request timed out"**

**Solutions:**
1. **Increase Timeout**
   - Go to node settings
   - Increase "Timeout" value (default: 300000ms = 5 minutes)
   - For slow APIs, increase to 600000ms (10 minutes)

2. **Optimize Request**
   - Add pagination for large datasets
   - Request only needed fields
   - Use filtering on API side
   - Consider caching responses

3. **Check API Health**
   - API might be down or slow
   - Test endpoint in browser/Postman
   - Check API status page

### SSL/TLS Errors

**"unable to verify the first certificate"**

**Solutions:**
1. **Ignore SSL Issues** (development only!)
   - In HTTP Request node settings
   - Enable "Ignore SSL Issues"
   - ⚠️ Not recommended for production

2. **Update Certificates**
   - Update system certificates
   - Contact API provider about SSL issues

### CORS Errors

**Note:** n8n workflows run server-side, so CORS shouldn't be an issue. If you see CORS errors:
- You might be testing in browser (test in n8n instead)
- The error might be from a different issue
- Check actual error message in execution logs

## Webhook Issues

### "Webhook waiting for response"

**Cause:** Webhook is in "Respond to Webhook" mode but no response sent

**Solution:**
```
Webhook Node (Wait for Webhook Call)
  → Process Data
  → Respond to Webhook Node (REQUIRED)
```

**Always add "Respond to Webhook" node when using "Wait for Webhook Call"**

### Webhook Not Triggering

**Debugging Steps:**
1. **Verify Workflow is Active**
   - Workflow must be activated (not just saved)
   - Check toggle switch in top-right is ON

2. **Check Webhook URL**
   - Copy exact URL from Webhook node
   - Verify no typos when configuring external service
   - Test with curl:
   ```bash
   curl -X POST https://your-n8n.com/webhook/your-path \
        -H "Content-Type: application/json" \
        -d '{"test": "data"}'
   ```

3. **Verify HTTP Method**
   - Webhook expects POST but receiving GET (or vice versa)
   - Match method in Webhook node config

4. **Check Authentication**
   - If "Webhook Authentication" is set, include credentials
   - Verify Header Auth name and value match

5. **Firewall/Network Issues**
   - n8n instance must be accessible from internet
   - Check firewall rules
   - Verify DNS is resolving correctly

### Webhook Returns Error to Caller

**Customize response:**
```
Webhook → IF Node
  → Success Path → Respond (200 OK)
  → Error Path → Respond to Webhook (400/500 with error message)
```

Use "Respond to Webhook" node to control:
- Status code
- Headers
- Response body
- Response format (JSON, text, etc.)

## Data Transformation Problems

### Empty Results After Transformation

**Cause:** Filter or map returns empty array

**Debugging:**
```javascript
// Check what data looks like before transformation
// Add a Set node to inspect: {{ $json }}

// Ensure filter condition is correct
{{ $json.items.filter(item => item.status === 'active') }}

// Check if property exists
{{ $json.items.filter(item => item.status && item.status === 'active') }}

// Verify array is actually an array
{{ Array.isArray($json.items) ? $json.items.length : 0 }}
```

### Data Type Mismatches

**String vs Number Issues:**
```javascript
// Problem: Comparing string with number
{{ $json.age > 18 }} // Fails if age is "25" (string)

// Solution: Parse to number
{{ parseInt($json.age) > 18 }}
{{ parseFloat($json.price) > 99.99 }}

// Problem: Math on strings
{{ $json.price * 1.2 }} // Fails if price is "$99.99"

// Solution: Clean and parse
{{ parseFloat($json.price.replace('$', '')) * 1.2 }}
```

### JSON Parse Errors

**"Unexpected token in JSON"**

**Solutions:**
```javascript
// Problem: Invalid JSON string
JSON.parse($json.data)

// Solution: Validate first (in Code node)
try {
  const data = JSON.parse(items[0].json.rawData);
  return [{ json: data }];
} catch (error) {
  return [{ json: {
    error: 'Invalid JSON',
    raw: items[0].json.rawData
  }}];
}

// Solution: Check if already an object
if (typeof $json.data === 'string') {
  JSON.parse($json.data)
} else {
  $json.data
}
```

## Performance Issues

### Workflow Execution Too Slow

**Solutions:**

1. **Reduce HTTP Requests**
   ```
   // Bad: Loop making individual requests
   Loop → HTTP Request (100x)

   // Good: Batch request
   Batch Items → HTTP Request with array
   ```

2. **Use Split In Batches**
   ```
   Split In Batches (batch size: 10)
     → Process Batch
     → Loop Back
   ```

3. **Optimize Expressions**
   ```javascript
   // Bad: Complex expression repeated
   {{ $json.items.filter(...).map(...).reduce(...) }}

   // Good: Use Code node for complex logic
   const result = items[0].json.items
     .filter(item => item.active)
     .map(item => item.value)
     .reduce((sum, val) => sum + val, 0);
   return [{ json: { total: result } }];
   ```

4. **Cache Frequently Accessed Data**
   - Store results in Set node
   - Reuse instead of re-fetching
   - Consider using database for persistent cache

### Memory Errors

**"JavaScript heap out of memory"**

**Solutions:**
1. **Process in Batches**
   - Don't load all data at once
   - Use Split In Batches node
   - Process incrementally

2. **Reduce Item Count**
   - Add Limit node after triggers
   - Use pagination in API requests
   - Filter data at source

3. **Optimize Data Size**
   - Remove unnecessary fields with Set node
   - Don't store large binary data in JSON
   - Use binary data type for files

## Execution Errors

### "Workflow did not finish"

**Causes:**
1. **Infinite Loop**
   - Missing stop condition in loop
   - Always include maximum iterations

2. **Timeout**
   - Workflow taking too long
   - Default timeout might be exceeded
   - Optimize or increase timeout settings

### "Missing node parameter"

**Cause:** Required field is empty or expression evaluates to empty

**Solutions:**
```javascript
// Provide default values
{{ $json.email || 'noreply@example.com' }}

// Validate before using
{{ $json.userId ? $json.userId : 'default-id' }}

// Use IF node to branch based on data availability
IF node: {{ $json.email !== undefined && $json.email !== '' }}
  → True: Continue with email
  → False: Skip or use default
```

### Workflow Executes Multiple Times

**Causes:**
1. **Trigger Firing Multiple Times**
   - Webhook called multiple times by external service
   - Schedule trigger overlapping with long execution
   - Email trigger processing same email multiple times

**Solutions:**
- Add deduplication logic
- Use IF node to check if already processed
- Store processed IDs in database
- Adjust trigger settings (e.g., mark emails as read)

## Node-Specific Issues

### Code Node Issues

**"items is not defined"**
```javascript
// Wrong: Using old syntax
for (item of items) { }

// Correct: Access items array
for (const item of items) { }

// Or use functional approach
return items.map(item => ({
  json: {
    // transformed data
  }
}));
```

**"Must return array"**
```javascript
// Wrong: Returning object
return { json: { value: 123 } };

// Correct: Return array of items
return [{ json: { value: 123 } }];

// Multiple items
return [
  { json: { id: 1 } },
  { json: { id: 2 } }
];
```

### Set Node Issues

**"Expression error in field"**
- Check expression syntax
- Verify referenced node names
- Test expression in expression editor
- Use debug panel to see available data

### IF Node Issues

**"All items ending up in one branch"**
- Verify condition logic
- Check data types (string vs number)
- Use debug panel to see actual values
- Test condition in expression editor

### Split In Batches Issues

**"Loop not completing"**
- Ensure "Loop Over Items" is connected back to Split In Batches
- Verify batch size is appropriate
- Check for errors in loop that stop execution

## General Debugging Tips

1. **Use Debug Panel**
   - Click on node to see input/output
   - Inspect data structure before writing expressions
   - Check for null/undefined values

2. **Test Incrementally**
   - Build workflow step by step
   - Test each node before adding next
   - Use "Execute Node" to test individual nodes

3. **Add Logging**
   ```javascript
   // In Code node
   console.log('Debug info:', items[0].json);
   // View in execution logs
   ```

4. **Use Set Nodes for Debugging**
   ```javascript
   // Add Set node with debug fields
   debug_field: {{ $json }}
   debug_type: {{ typeof $json.value }}
   debug_length: {{ $json.items?.length }}
   ```

5. **Check Execution Logs**
   - View past executions
   - Look for error messages
   - Compare successful vs failed runs

6. **Simplify**
   - Remove complex expressions temporarily
   - Use static values to isolate issues
   - Test with minimal data first

7. **Read Error Messages Carefully**
   - Error often points to exact issue
   - Note line numbers in Code nodes
   - Google specific error messages

## Getting Help

If you're still stuck:

1. **Check n8n Documentation**
   - https://docs.n8n.io/
   - Node-specific docs
   - Expression reference

2. **Community Forum**
   - https://community.n8n.io/
   - Search for similar issues
   - Post workflow JSON for help

3. **GitHub Issues**
   - https://github.com/n8n-io/n8n
   - Report bugs
   - Check known issues

4. **Export Workflow**
   - Download as JSON for sharing
   - Remove sensitive credentials
   - Include error messages when asking for help

## Quick Reference: Common Error Messages

| Error | Common Cause | Solution |
|-------|-------------|----------|
| 401 Unauthorized | Wrong credentials | Check credential, verify API key |
| 403 Forbidden | Insufficient permissions | Check API permissions, IP whitelist |
| 404 Not Found | Wrong URL/endpoint | Verify URL, check API docs |
| 500 Internal Server Error | API issue or bad request | Check request body, verify API status |
| Timeout | Request too slow | Increase timeout, optimize request |
| Expression error | Syntax or missing data | Check syntax, verify node names |
| Cannot read property | Undefined value | Use optional chaining `?.` |
| Node not found | Wrong node name | Match exact node name (case-sensitive) |
| Invalid DateTime | Bad date format | Validate date before parsing |
| JavaScript heap out of memory | Too much data | Process in batches, reduce data size |
