# n8n-best-practices
> Use when encountering n8n workflow issues, Code node errors, HTTP requests failing, data flow problems, environment variables not working, JSON parsing errors, or need n8n development patterns and debugging strategies
- Author: aixier
- Repository: aixier/n8n-automation-hub
- Version: 20251103195900
- Stars: 0
- Forks: 0
- Last Updated: 2026-02-07
- Source: https://github.com/aixier/n8n-automation-hub
- Web: https://mule.run/skillshub/@@aixier/n8n-automation-hub~n8n-best-practices:20251103195900
---
---
name: n8n-best-practices
description: Use when encountering n8n workflow issues, Code node errors, HTTP requests failing, data flow problems, environment variables not working, JSON parsing errors, or need n8n development patterns and debugging strategies
---
# n8n Best Practices
**When to use this skill**: Any time you're working with n8n workflows and encounter errors, unexpected behavior, or need guidance on implementation patterns.
## Critical Knowledge Base
### 🚨 ES5 Syntax Only in Code Nodes
n8n Code nodes **only support ES5 JavaScript**. Modern ES6+ syntax will fail.
**❌ DO NOT USE:**
```javascript
// Arrow functions
const process = (item) => item.value;
// Template literals
const url = `https://api.example.com/${id}`;
// const/let
const value = 123;
// Destructuring
const { name, age } = person;
// Spread operator in function calls
Math.max(...numbers);
```
**✅ USE INSTEAD:**
```javascript
// Regular functions
var process = function(item) {
return item.value;
};
// String concatenation
var url = 'https://api.example.com/' + id;
// var only
var value = 123;
// Manual assignment
var name = person.name;
var age = person.age;
// apply() for spread
Math.max.apply(null, numbers);
// Object spread alternative
var merged = Object.assign({}, obj1, obj2);
```
### 🌐 HTTP Requests in Code Nodes
**CRITICAL**: `$http` and `axios` are NOT available in Code nodes.
**❌ WRONG:**
```javascript
const response = await $http.request({url: 'https://api.example.com'});
const axios = require('axios');
```
**✅ CORRECT - Use Native HTTPS:**
```javascript
var https = require('https');
function makeRequest(url, options) {
return new Promise(function(resolve, reject) {
var req = https.request(options, function(res) {
var data = '';
res.on('data', function(chunk) { data += chunk; });
res.on('end', function() {
resolve({statusCode: res.statusCode, body: data});
});
});
req.on('error', reject);
req.end();
});
}
// Usage
var result = await makeRequest('example.com', {
hostname: 'example.com',
path: '/api/endpoint',
method: 'POST',
headers: {'Content-Type': 'application/json'}
});
```
### 🔐 Environment Variables Configuration
**CRITICAL**: Variables must be explicitly exported, not just sourced.
**❌ WRONG:**
```bash
source .env.local
pnpm start
# Variables will be undefined in Code nodes!
```
**✅ CORRECT:**
```bash
#!/bin/bash
export NOTION_API_KEY=$(grep NOTION_API_KEY .env.local | cut -d '=' -f2)
export QWEN_API_KEY=$(grep QWEN_API_KEY .env.local | cut -d '=' -f2)
export NODE_FUNCTION_ALLOW_BUILTIN=*
export N8N_BLOCK_ENV_ACCESS_IN_NODE=false
pnpm start
```
**Access in Code nodes:**
```javascript
var apiKey = process.env.NOTION_API_KEY; // Not $env
```
### 📦 gzip Compression Issues
**Problem**: HTTP requests with gzip compression return garbled data.
**❌ WRONG:**
```javascript
headers: {
'Accept-Encoding': 'gzip, deflate'
}
// Returns: �������
```
**✅ CORRECT:**
```javascript
headers: {
'Content-Type': 'application/json'
// DO NOT include Accept-Encoding header
}
```
### 🔄 Data Flow Patterns
**Always preserve upstream data:**
**✅ CORRECT:**
```javascript
return {
json: Object.assign({}, $input.item.json, {
newField: newValue
})
};
```
**❌ WRONG:**
```javascript
return {
json: {
newField: newValue // Loses all previous data!
}
};
```
### 📋 JSON Parsing Best Practices
**❌ WRONG:**
```javascript
var data = JSON.parse(response);
// May return undefined without error
```
**✅ CORRECT:**
```javascript
function safeJSONParse(text) {
try {
var parsed = JSON.parse(text);
if (parsed && typeof parsed === 'object') {
return parsed;
}
throw new Error('Parsed value is not an object');
} catch (e) {
throw new Error('JSON parsing failed: ' + e.message);
}
}
var data = safeJSONParse(response);
```
### 🔧 Code Node Sandbox Configuration
**macOS launchd service:**
```xml
EnvironmentVariables
NODE_FUNCTION_ALLOW_BUILTIN
*
```
**Shell script:**
```bash
export NODE_FUNCTION_ALLOW_BUILTIN=*
n8n start
```
### 🐛 Common Pitfalls
**1. Aggregate Node Array Wrapping**
```javascript
// Aggregate converts: {field: value} → {field: [value]}
var data = $input.first().json;
var actualValue = data.field[0]; // Must access array
```
**2. Split Into Batches Data Loss**
```javascript
// ❌ WRONG: Loses data
return items.map(function(item) {
return {json: {processed: true}};
});
// ✅ CORRECT: Preserves data
return items.map(function(item) {
return {
json: Object.assign({}, item.json, {processed: true})
};
});
```
**3. require() Module Access**
```javascript
// Only available if NODE_FUNCTION_ALLOW_BUILTIN=*
var https = require('https'); // ✅ Works
var axios = require('axios'); // ❌ Not available
```
## Quick Reference
### When Code node fails:
1. Check ES5 syntax (no arrow functions, template literals)
2. Verify environment variables are exported
3. Use `require('https')` not `$http`
4. Remove `Accept-Encoding` header for gzip issues
### When data is lost:
1. Always spread previous data: `Object.assign({}, $input.item.json, newData)`
2. Check Aggregate node array wrapping
3. Verify Split Into Batches preserves data
### When environment variables are undefined:
1. Use `export`, not `source`
2. Access with `process.env.VAR`, not `$env.VAR`
3. Set `N8N_BLOCK_ENV_ACCESS_IN_NODE=false`
## Full Documentation
For complete details, examples, and advanced patterns, see:
`/mnt/d/work/n8n_agent/n8n-skills/n8n-best-practices/README.md`