Comprehensive skill for n8n workflow automation including: - Workflow design and node configuration - Expression writing reference (14 KB) - Comprehensive troubleshooting guide (15 KB) - Examples for common use cases - Performance optimization tips 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
15 KiB
n8n Troubleshooting Guide
Common issues and solutions for n8n workflow debugging.
Table of Contents
- Authentication Errors
- Expression Errors
- HTTP Request Errors
- Webhook Issues
- Data Transformation Problems
- Performance Issues
- Execution Errors
- Node-Specific Issues
Authentication Errors
401 Unauthorized
Symptoms:
- HTTP Request node returns 401 status code
- Error message: "Unauthorized" or "Invalid credentials"
Common Causes & Solutions:
-
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
-
Expired Token
- OAuth2 tokens expire - reconnect the credential
- API keys may have expiration dates - check provider dashboard
- Refresh tokens if using OAuth2
-
Wrong Authentication Method
- Verify API requires Bearer token, Basic Auth, or API Key
- Check API documentation for correct header format
- Common headers:
Authorization: Bearer TOKENAuthorization: Basic BASE64_CREDENTIALSX-API-Key: YOUR_KEY
-
Missing Headers
// Common required headers { "Authorization": "Bearer YOUR_TOKEN", "Content-Type": "application/json", "User-Agent": "n8n-workflow" } -
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:
# 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:
-
Insufficient Permissions
- API key/token lacks permission for the resource
- Check if account has access to the endpoint
- Verify subscription/plan level
-
IP Whitelist
- Some APIs require IP whitelisting
- Add n8n server IP to allowed list
- Check firewall rules
-
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:
// 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:
// 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:
- Check node name exactly as it appears in workflow
- Node names are case-sensitive
- Spaces and special characters must match exactly
- Renamed nodes? Update all expressions
Expression Syntax Errors
Common Mistakes:
// 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"
// 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:
-
Verify URL
// 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 -
Check API Endpoint
- Endpoint may have changed (check API docs)
- Verify API version in URL
- Check for typos in path
-
Resource Doesn't Exist
- ID might be invalid
- Resource might have been deleted
- Test with known valid ID
Timeout Errors
"Request timed out"
Solutions:
-
Increase Timeout
- Go to node settings
- Increase "Timeout" value (default: 300000ms = 5 minutes)
- For slow APIs, increase to 600000ms (10 minutes)
-
Optimize Request
- Add pagination for large datasets
- Request only needed fields
- Use filtering on API side
- Consider caching responses
-
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:
-
Ignore SSL Issues (development only!)
- In HTTP Request node settings
- Enable "Ignore SSL Issues"
- ⚠️ Not recommended for production
-
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:
-
Verify Workflow is Active
- Workflow must be activated (not just saved)
- Check toggle switch in top-right is ON
-
Check Webhook URL
- Copy exact URL from Webhook node
- Verify no typos when configuring external service
- Test with curl:
curl -X POST https://your-n8n.com/webhook/your-path \ -H "Content-Type: application/json" \ -d '{"test": "data"}' -
Verify HTTP Method
- Webhook expects POST but receiving GET (or vice versa)
- Match method in Webhook node config
-
Check Authentication
- If "Webhook Authentication" is set, include credentials
- Verify Header Auth name and value match
-
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:
// 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:
// 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:
// 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:
-
Reduce HTTP Requests
// Bad: Loop making individual requests Loop → HTTP Request (100x) // Good: Batch request Batch Items → HTTP Request with array -
Use Split In Batches
Split In Batches (batch size: 10) → Process Batch → Loop Back -
Optimize Expressions
// 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 } }]; -
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:
-
Process in Batches
- Don't load all data at once
- Use Split In Batches node
- Process incrementally
-
Reduce Item Count
- Add Limit node after triggers
- Use pagination in API requests
- Filter data at source
-
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:
-
Infinite Loop
- Missing stop condition in loop
- Always include maximum iterations
-
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:
// 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:
- 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"
// 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"
// 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
-
Use Debug Panel
- Click on node to see input/output
- Inspect data structure before writing expressions
- Check for null/undefined values
-
Test Incrementally
- Build workflow step by step
- Test each node before adding next
- Use "Execute Node" to test individual nodes
-
Add Logging
// In Code node console.log('Debug info:', items[0].json); // View in execution logs -
Use Set Nodes for Debugging
// Add Set node with debug fields debug_field: {{ $json }} debug_type: {{ typeof $json.value }} debug_length: {{ $json.items?.length }} -
Check Execution Logs
- View past executions
- Look for error messages
- Compare successful vs failed runs
-
Simplify
- Remove complex expressions temporarily
- Use static values to isolate issues
- Test with minimal data first
-
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:
-
Check n8n Documentation
- https://docs.n8n.io/
- Node-specific docs
- Expression reference
-
Community Forum
- https://community.n8n.io/
- Search for similar issues
- Post workflow JSON for help
-
GitHub Issues
- https://github.com/n8n-io/n8n
- Report bugs
- Check known issues
-
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 |