# 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 |