bps-kit 1.2.2 → 1.3.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.bps-kit.json +4 -4
- package/README.md +3 -0
- package/implementation_plan.md.resolved +37 -0
- package/package.json +2 -2
- package/templates/agents-template/ARCHITECTURE.md +21 -9
- package/templates/agents-template/agents/automation-specialist.md +157 -0
- package/templates/agents-template/rules/GEMINI.md +2 -10
- package/templates/agents-template/workflows/automate.md +153 -0
- package/templates/skills_normal/n8n-code-javascript/BUILTIN_FUNCTIONS.md +764 -0
- package/templates/skills_normal/n8n-code-javascript/COMMON_PATTERNS.md +1110 -0
- package/templates/skills_normal/n8n-code-javascript/DATA_ACCESS.md +782 -0
- package/templates/skills_normal/n8n-code-javascript/ERROR_PATTERNS.md +763 -0
- package/templates/skills_normal/n8n-code-javascript/README.md +350 -0
- package/templates/skills_normal/n8n-code-javascript/SKILL.md +699 -0
- package/templates/skills_normal/n8n-code-python/COMMON_PATTERNS.md +794 -0
- package/templates/skills_normal/n8n-code-python/DATA_ACCESS.md +702 -0
- package/templates/skills_normal/n8n-code-python/ERROR_PATTERNS.md +601 -0
- package/templates/skills_normal/n8n-code-python/README.md +386 -0
- package/templates/skills_normal/n8n-code-python/SKILL.md +748 -0
- package/templates/skills_normal/n8n-code-python/STANDARD_LIBRARY.md +974 -0
- package/templates/skills_normal/n8n-expression-syntax/COMMON_MISTAKES.md +393 -0
- package/templates/skills_normal/n8n-expression-syntax/EXAMPLES.md +483 -0
- package/templates/skills_normal/n8n-expression-syntax/README.md +93 -0
- package/templates/skills_normal/n8n-expression-syntax/SKILL.md +516 -0
- package/templates/skills_normal/n8n-mcp-tools-expert/README.md +99 -0
- package/templates/skills_normal/n8n-mcp-tools-expert/SEARCH_GUIDE.md +374 -0
- package/templates/skills_normal/n8n-mcp-tools-expert/SKILL.md +642 -0
- package/templates/skills_normal/n8n-mcp-tools-expert/VALIDATION_GUIDE.md +442 -0
- package/templates/skills_normal/n8n-mcp-tools-expert/WORKFLOW_GUIDE.md +618 -0
- package/templates/skills_normal/n8n-node-configuration/DEPENDENCIES.md +789 -0
- package/templates/skills_normal/n8n-node-configuration/OPERATION_PATTERNS.md +913 -0
- package/templates/skills_normal/n8n-node-configuration/README.md +364 -0
- package/templates/skills_normal/n8n-node-configuration/SKILL.md +785 -0
- package/templates/skills_normal/n8n-validation-expert/ERROR_CATALOG.md +943 -0
- package/templates/skills_normal/n8n-validation-expert/FALSE_POSITIVES.md +720 -0
- package/templates/skills_normal/n8n-validation-expert/README.md +290 -0
- package/templates/skills_normal/n8n-validation-expert/SKILL.md +689 -0
- package/templates/skills_normal/n8n-workflow-patterns/README.md +251 -0
- package/templates/skills_normal/n8n-workflow-patterns/SKILL.md +411 -0
- package/templates/skills_normal/n8n-workflow-patterns/ai_agent_workflow.md +784 -0
- package/templates/skills_normal/n8n-workflow-patterns/database_operations.md +785 -0
- package/templates/skills_normal/n8n-workflow-patterns/http_api_integration.md +734 -0
- package/templates/skills_normal/n8n-workflow-patterns/scheduled_tasks.md +773 -0
- package/templates/skills_normal/n8n-workflow-patterns/webhook_processing.md +545 -0
- package/templates/vault/n8n-code-javascript/SKILL.md +10 -10
- package/templates/vault/n8n-code-python/SKILL.md +11 -11
- package/templates/vault/n8n-expression-syntax/SKILL.md +4 -4
- package/templates/vault/n8n-mcp-tools-expert/SKILL.md +9 -9
- package/templates/vault/n8n-node-configuration/SKILL.md +2 -2
- package/templates/vault/n8n-validation-expert/SKILL.md +3 -3
- package/templates/vault/n8n-workflow-patterns/SKILL.md +11 -11
|
@@ -0,0 +1,763 @@
|
|
|
1
|
+
# Error Patterns - JavaScript Code Node
|
|
2
|
+
|
|
3
|
+
Complete guide to avoiding the most common Code node errors.
|
|
4
|
+
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## Overview
|
|
8
|
+
|
|
9
|
+
This guide covers the **top 5 error patterns** encountered in n8n Code nodes. Understanding and avoiding these errors will save you significant debugging time.
|
|
10
|
+
|
|
11
|
+
**Error Frequency**:
|
|
12
|
+
1. Empty Code / Missing Return - **38% of failures**
|
|
13
|
+
2. Expression Syntax Confusion - **8% of failures**
|
|
14
|
+
3. Incorrect Return Wrapper - **5% of failures**
|
|
15
|
+
4. Unmatched Expression Brackets - **6% of failures**
|
|
16
|
+
5. Missing Null Checks - **Common runtime error**
|
|
17
|
+
|
|
18
|
+
---
|
|
19
|
+
|
|
20
|
+
## Error #1: Empty Code or Missing Return Statement
|
|
21
|
+
|
|
22
|
+
**Frequency**: Most common error (38% of all validation failures)
|
|
23
|
+
|
|
24
|
+
**What Happens**:
|
|
25
|
+
- Workflow execution fails
|
|
26
|
+
- Next nodes receive no data
|
|
27
|
+
- Error: "Code cannot be empty" or "Code must return data"
|
|
28
|
+
|
|
29
|
+
### The Problem
|
|
30
|
+
|
|
31
|
+
```javascript
|
|
32
|
+
// ❌ ERROR: No code at all
|
|
33
|
+
// (Empty code field)
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
```javascript
|
|
37
|
+
// ❌ ERROR: Code executes but doesn't return anything
|
|
38
|
+
const items = $input.all();
|
|
39
|
+
|
|
40
|
+
// Process items
|
|
41
|
+
for (const item of items) {
|
|
42
|
+
console.log(item.json.name);
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
// Forgot to return!
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
```javascript
|
|
49
|
+
// ❌ ERROR: Early return path exists, but not all paths return
|
|
50
|
+
const items = $input.all();
|
|
51
|
+
|
|
52
|
+
if (items.length === 0) {
|
|
53
|
+
return []; // ✅ This path returns
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
// Process items
|
|
57
|
+
const processed = items.map(item => ({json: item.json}));
|
|
58
|
+
|
|
59
|
+
// ❌ Forgot to return processed!
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
### The Solution
|
|
63
|
+
|
|
64
|
+
```javascript
|
|
65
|
+
// ✅ CORRECT: Always return data
|
|
66
|
+
const items = $input.all();
|
|
67
|
+
|
|
68
|
+
// Process items
|
|
69
|
+
const processed = items.map(item => ({
|
|
70
|
+
json: {
|
|
71
|
+
...item.json,
|
|
72
|
+
processed: true
|
|
73
|
+
}
|
|
74
|
+
}));
|
|
75
|
+
|
|
76
|
+
return processed; // ✅ Return statement present
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
```javascript
|
|
80
|
+
// ✅ CORRECT: Return empty array if no items
|
|
81
|
+
const items = $input.all();
|
|
82
|
+
|
|
83
|
+
if (items.length === 0) {
|
|
84
|
+
return []; // Valid: empty array when no data
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
// Process and return
|
|
88
|
+
return items.map(item => ({json: item.json}));
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
```javascript
|
|
92
|
+
// ✅ CORRECT: All code paths return
|
|
93
|
+
const items = $input.all();
|
|
94
|
+
|
|
95
|
+
if (items.length === 0) {
|
|
96
|
+
return [];
|
|
97
|
+
} else if (items.length === 1) {
|
|
98
|
+
return [{json: {single: true, data: items[0].json}}];
|
|
99
|
+
} else {
|
|
100
|
+
return items.map(item => ({json: item.json}));
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
// All paths covered
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
### Checklist
|
|
107
|
+
|
|
108
|
+
- [ ] Code field is not empty
|
|
109
|
+
- [ ] Return statement exists
|
|
110
|
+
- [ ] ALL code paths return data (if/else branches)
|
|
111
|
+
- [ ] Return format is correct (`[{json: {...}}]`)
|
|
112
|
+
- [ ] Return happens even on errors (use try-catch)
|
|
113
|
+
|
|
114
|
+
---
|
|
115
|
+
|
|
116
|
+
## Error #2: Expression Syntax Confusion
|
|
117
|
+
|
|
118
|
+
**Frequency**: 8% of validation failures
|
|
119
|
+
|
|
120
|
+
**What Happens**:
|
|
121
|
+
- Syntax error in code execution
|
|
122
|
+
- Error: "Unexpected token" or "Expression syntax is not valid in Code nodes"
|
|
123
|
+
- Template variables not evaluated
|
|
124
|
+
|
|
125
|
+
### The Problem
|
|
126
|
+
|
|
127
|
+
n8n has TWO distinct syntaxes:
|
|
128
|
+
1. **Expression syntax** `{{ }}` - Used in OTHER nodes (Set, IF, HTTP Request)
|
|
129
|
+
2. **JavaScript** - Used in CODE nodes (no `{{ }}`)
|
|
130
|
+
|
|
131
|
+
Many developers mistakenly use expression syntax inside Code nodes.
|
|
132
|
+
|
|
133
|
+
```javascript
|
|
134
|
+
// ❌ WRONG: Using n8n expression syntax in Code node
|
|
135
|
+
const userName = "{{ $json.name }}";
|
|
136
|
+
const userEmail = "{{ $json.body.email }}";
|
|
137
|
+
|
|
138
|
+
return [{
|
|
139
|
+
json: {
|
|
140
|
+
name: userName,
|
|
141
|
+
email: userEmail
|
|
142
|
+
}
|
|
143
|
+
}];
|
|
144
|
+
|
|
145
|
+
// Result: Literal string "{{ $json.name }}", NOT the value!
|
|
146
|
+
```
|
|
147
|
+
|
|
148
|
+
```javascript
|
|
149
|
+
// ❌ WRONG: Trying to evaluate expressions
|
|
150
|
+
const value = "{{ $now.toFormat('yyyy-MM-dd') }}";
|
|
151
|
+
```
|
|
152
|
+
|
|
153
|
+
### The Solution
|
|
154
|
+
|
|
155
|
+
```javascript
|
|
156
|
+
// ✅ CORRECT: Use JavaScript directly (no {{ }})
|
|
157
|
+
const userName = $json.name;
|
|
158
|
+
const userEmail = $json.body.email;
|
|
159
|
+
|
|
160
|
+
return [{
|
|
161
|
+
json: {
|
|
162
|
+
name: userName,
|
|
163
|
+
email: userEmail
|
|
164
|
+
}
|
|
165
|
+
}];
|
|
166
|
+
```
|
|
167
|
+
|
|
168
|
+
```javascript
|
|
169
|
+
// ✅ CORRECT: JavaScript template literals (use backticks)
|
|
170
|
+
const message = `Hello, ${$json.name}! Your email is ${$json.email}`;
|
|
171
|
+
|
|
172
|
+
return [{
|
|
173
|
+
json: {
|
|
174
|
+
greeting: message
|
|
175
|
+
}
|
|
176
|
+
}];
|
|
177
|
+
```
|
|
178
|
+
|
|
179
|
+
```javascript
|
|
180
|
+
// ✅ CORRECT: Direct variable access
|
|
181
|
+
const item = $input.first().json;
|
|
182
|
+
|
|
183
|
+
return [{
|
|
184
|
+
json: {
|
|
185
|
+
name: item.name,
|
|
186
|
+
email: item.email,
|
|
187
|
+
timestamp: new Date().toISOString() // JavaScript Date, not {{ }}
|
|
188
|
+
}
|
|
189
|
+
}];
|
|
190
|
+
```
|
|
191
|
+
|
|
192
|
+
### Comparison Table
|
|
193
|
+
|
|
194
|
+
| Context | Syntax | Example |
|
|
195
|
+
|---------|--------|---------|
|
|
196
|
+
| Set node | `{{ }}` expressions | `{{ $json.name }}` |
|
|
197
|
+
| IF node | `{{ }}` expressions | `{{ $json.age > 18 }}` |
|
|
198
|
+
| HTTP Request URL | `{{ }}` expressions | `{{ $json.userId }}` |
|
|
199
|
+
| **Code node** | **JavaScript** | `$json.name` |
|
|
200
|
+
| **Code node strings** | **Template literals** | `` `Hello ${$json.name}` `` |
|
|
201
|
+
|
|
202
|
+
### Quick Fix Guide
|
|
203
|
+
|
|
204
|
+
```javascript
|
|
205
|
+
// WRONG → RIGHT conversions
|
|
206
|
+
|
|
207
|
+
// ❌ "{{ $json.field }}"
|
|
208
|
+
// ✅ $json.field
|
|
209
|
+
|
|
210
|
+
// ❌ "{{ $now }}"
|
|
211
|
+
// ✅ new Date().toISOString()
|
|
212
|
+
|
|
213
|
+
// ❌ "{{ $node['HTTP Request'].json.data }}"
|
|
214
|
+
// ✅ $node["HTTP Request"].json.data
|
|
215
|
+
|
|
216
|
+
// ❌ `{{ $json.firstName }} {{ $json.lastName }}`
|
|
217
|
+
// ✅ `${$json.firstName} ${$json.lastName}`
|
|
218
|
+
```
|
|
219
|
+
|
|
220
|
+
---
|
|
221
|
+
|
|
222
|
+
## Error #3: Incorrect Return Wrapper Format
|
|
223
|
+
|
|
224
|
+
**Frequency**: 5% of validation failures
|
|
225
|
+
|
|
226
|
+
**What Happens**:
|
|
227
|
+
- Error: "Return value must be an array of objects"
|
|
228
|
+
- Error: "Each item must have a json property"
|
|
229
|
+
- Next nodes receive malformed data
|
|
230
|
+
|
|
231
|
+
### The Problem
|
|
232
|
+
|
|
233
|
+
Code nodes MUST return:
|
|
234
|
+
- **Array** of objects
|
|
235
|
+
- Each object MUST have a **`json` property**
|
|
236
|
+
|
|
237
|
+
```javascript
|
|
238
|
+
// ❌ WRONG: Returning object instead of array
|
|
239
|
+
return {
|
|
240
|
+
json: {
|
|
241
|
+
result: 'success'
|
|
242
|
+
}
|
|
243
|
+
};
|
|
244
|
+
// Missing array wrapper []
|
|
245
|
+
```
|
|
246
|
+
|
|
247
|
+
```javascript
|
|
248
|
+
// ❌ WRONG: Returning array without json wrapper
|
|
249
|
+
return [
|
|
250
|
+
{id: 1, name: 'Alice'},
|
|
251
|
+
{id: 2, name: 'Bob'}
|
|
252
|
+
];
|
|
253
|
+
// Missing json property
|
|
254
|
+
```
|
|
255
|
+
|
|
256
|
+
```javascript
|
|
257
|
+
// ❌ WRONG: Returning plain value
|
|
258
|
+
return "processed";
|
|
259
|
+
```
|
|
260
|
+
|
|
261
|
+
```javascript
|
|
262
|
+
// ❌ WRONG: Returning items without mapping
|
|
263
|
+
return $input.all();
|
|
264
|
+
// Works if items already have json property, but not guaranteed
|
|
265
|
+
```
|
|
266
|
+
|
|
267
|
+
```javascript
|
|
268
|
+
// ❌ WRONG: Incomplete structure
|
|
269
|
+
return [{data: {result: 'success'}}];
|
|
270
|
+
// Should be {json: {...}}, not {data: {...}}
|
|
271
|
+
```
|
|
272
|
+
|
|
273
|
+
### The Solution
|
|
274
|
+
|
|
275
|
+
```javascript
|
|
276
|
+
// ✅ CORRECT: Single result
|
|
277
|
+
return [{
|
|
278
|
+
json: {
|
|
279
|
+
result: 'success',
|
|
280
|
+
timestamp: new Date().toISOString()
|
|
281
|
+
}
|
|
282
|
+
}];
|
|
283
|
+
```
|
|
284
|
+
|
|
285
|
+
```javascript
|
|
286
|
+
// ✅ CORRECT: Multiple results
|
|
287
|
+
return [
|
|
288
|
+
{json: {id: 1, name: 'Alice'}},
|
|
289
|
+
{json: {id: 2, name: 'Bob'}},
|
|
290
|
+
{json: {id: 3, name: 'Carol'}}
|
|
291
|
+
];
|
|
292
|
+
```
|
|
293
|
+
|
|
294
|
+
```javascript
|
|
295
|
+
// ✅ CORRECT: Transforming array
|
|
296
|
+
const items = $input.all();
|
|
297
|
+
|
|
298
|
+
return items.map(item => ({
|
|
299
|
+
json: {
|
|
300
|
+
id: item.json.id,
|
|
301
|
+
name: item.json.name,
|
|
302
|
+
processed: true
|
|
303
|
+
}
|
|
304
|
+
}));
|
|
305
|
+
```
|
|
306
|
+
|
|
307
|
+
```javascript
|
|
308
|
+
// ✅ CORRECT: Empty result
|
|
309
|
+
return [];
|
|
310
|
+
// Valid when no data to return
|
|
311
|
+
```
|
|
312
|
+
|
|
313
|
+
```javascript
|
|
314
|
+
// ✅ CORRECT: Conditional returns
|
|
315
|
+
if (shouldProcess) {
|
|
316
|
+
return [{json: {result: 'processed'}}];
|
|
317
|
+
} else {
|
|
318
|
+
return [];
|
|
319
|
+
}
|
|
320
|
+
```
|
|
321
|
+
|
|
322
|
+
### Return Format Checklist
|
|
323
|
+
|
|
324
|
+
- [ ] Return value is an **array** `[...]`
|
|
325
|
+
- [ ] Each array element has **`json` property**
|
|
326
|
+
- [ ] Structure is `[{json: {...}}]` or `[{json: {...}}, {json: {...}}]`
|
|
327
|
+
- [ ] NOT `{json: {...}}` (missing array wrapper)
|
|
328
|
+
- [ ] NOT `[{...}]` (missing json property)
|
|
329
|
+
|
|
330
|
+
### Common Scenarios
|
|
331
|
+
|
|
332
|
+
```javascript
|
|
333
|
+
// Scenario 1: Single object from API
|
|
334
|
+
const response = $input.first().json;
|
|
335
|
+
|
|
336
|
+
// ✅ CORRECT
|
|
337
|
+
return [{json: response}];
|
|
338
|
+
|
|
339
|
+
// ❌ WRONG
|
|
340
|
+
return {json: response};
|
|
341
|
+
|
|
342
|
+
|
|
343
|
+
// Scenario 2: Array of objects
|
|
344
|
+
const users = $input.all();
|
|
345
|
+
|
|
346
|
+
// ✅ CORRECT
|
|
347
|
+
return users.map(user => ({json: user.json}));
|
|
348
|
+
|
|
349
|
+
// ❌ WRONG
|
|
350
|
+
return users; // Risky - depends on existing structure
|
|
351
|
+
|
|
352
|
+
|
|
353
|
+
// Scenario 3: Computed result
|
|
354
|
+
const total = $input.all().reduce((sum, item) => sum + item.json.amount, 0);
|
|
355
|
+
|
|
356
|
+
// ✅ CORRECT
|
|
357
|
+
return [{json: {total}}];
|
|
358
|
+
|
|
359
|
+
// ❌ WRONG
|
|
360
|
+
return {total};
|
|
361
|
+
|
|
362
|
+
|
|
363
|
+
// Scenario 4: No results
|
|
364
|
+
// ✅ CORRECT
|
|
365
|
+
return [];
|
|
366
|
+
|
|
367
|
+
// ❌ WRONG
|
|
368
|
+
return null;
|
|
369
|
+
```
|
|
370
|
+
|
|
371
|
+
---
|
|
372
|
+
|
|
373
|
+
## Error #4: Unmatched Expression Brackets
|
|
374
|
+
|
|
375
|
+
**Frequency**: 6% of validation failures
|
|
376
|
+
|
|
377
|
+
**What Happens**:
|
|
378
|
+
- Parsing error during save
|
|
379
|
+
- Error: "Unmatched expression brackets"
|
|
380
|
+
- Code appears correct but fails validation
|
|
381
|
+
|
|
382
|
+
### The Problem
|
|
383
|
+
|
|
384
|
+
This error typically occurs when:
|
|
385
|
+
1. Strings contain unbalanced quotes
|
|
386
|
+
2. Multi-line strings with special characters
|
|
387
|
+
3. Template literals with nested brackets
|
|
388
|
+
|
|
389
|
+
```javascript
|
|
390
|
+
// ❌ WRONG: Unescaped quote in string
|
|
391
|
+
const message = "It's a nice day";
|
|
392
|
+
// Single quote breaks string
|
|
393
|
+
```
|
|
394
|
+
|
|
395
|
+
```javascript
|
|
396
|
+
// ❌ WRONG: Unbalanced brackets in regex
|
|
397
|
+
const pattern = /\{(\w+)\}/; // JSON storage issue
|
|
398
|
+
```
|
|
399
|
+
|
|
400
|
+
```javascript
|
|
401
|
+
// ❌ WRONG: Multi-line string with quotes
|
|
402
|
+
const html = "
|
|
403
|
+
<div class="container">
|
|
404
|
+
<p>Hello</p>
|
|
405
|
+
</div>
|
|
406
|
+
";
|
|
407
|
+
// Quote balance issues
|
|
408
|
+
```
|
|
409
|
+
|
|
410
|
+
### The Solution
|
|
411
|
+
|
|
412
|
+
```javascript
|
|
413
|
+
// ✅ CORRECT: Escape quotes
|
|
414
|
+
const message = "It\\'s a nice day";
|
|
415
|
+
// Or use different quotes
|
|
416
|
+
const message = "It's a nice day"; // Double quotes work
|
|
417
|
+
```
|
|
418
|
+
|
|
419
|
+
```javascript
|
|
420
|
+
// ✅ CORRECT: Escape regex properly
|
|
421
|
+
const pattern = /\\{(\\w+)\\}/;
|
|
422
|
+
```
|
|
423
|
+
|
|
424
|
+
```javascript
|
|
425
|
+
// ✅ CORRECT: Template literals for multi-line
|
|
426
|
+
const html = `
|
|
427
|
+
<div class="container">
|
|
428
|
+
<p>Hello</p>
|
|
429
|
+
</div>
|
|
430
|
+
`;
|
|
431
|
+
// Backticks handle multi-line and quotes
|
|
432
|
+
```
|
|
433
|
+
|
|
434
|
+
```javascript
|
|
435
|
+
// ✅ CORRECT: Escape backslashes
|
|
436
|
+
const path = "C:\\\\Users\\\\Documents\\\\file.txt";
|
|
437
|
+
```
|
|
438
|
+
|
|
439
|
+
### Escaping Guide
|
|
440
|
+
|
|
441
|
+
| Character | Escape As | Example |
|
|
442
|
+
|-----------|-----------|---------|
|
|
443
|
+
| Single quote in single-quoted string | `\\'` | `'It\\'s working'` |
|
|
444
|
+
| Double quote in double-quoted string | `\\"` | `"She said \\"hello\\""` |
|
|
445
|
+
| Backslash | `\\\\` | `"C:\\\\path"` |
|
|
446
|
+
| Newline | `\\n` | `"Line 1\\nLine 2"` |
|
|
447
|
+
| Tab | `\\t` | `"Column1\\tColumn2"` |
|
|
448
|
+
|
|
449
|
+
### Best Practices
|
|
450
|
+
|
|
451
|
+
```javascript
|
|
452
|
+
// ✅ BEST: Use template literals for complex strings
|
|
453
|
+
const message = `User ${name} said: "Hello!"`;
|
|
454
|
+
|
|
455
|
+
// ✅ BEST: Use template literals for HTML
|
|
456
|
+
const html = `
|
|
457
|
+
<div class="${className}">
|
|
458
|
+
<h1>${title}</h1>
|
|
459
|
+
<p>${content}</p>
|
|
460
|
+
</div>
|
|
461
|
+
`;
|
|
462
|
+
|
|
463
|
+
// ✅ BEST: Use template literals for JSON
|
|
464
|
+
const jsonString = `{
|
|
465
|
+
"name": "${name}",
|
|
466
|
+
"email": "${email}"
|
|
467
|
+
}`;
|
|
468
|
+
```
|
|
469
|
+
|
|
470
|
+
---
|
|
471
|
+
|
|
472
|
+
## Error #5: Missing Null Checks / Undefined Access
|
|
473
|
+
|
|
474
|
+
**Frequency**: Very common runtime error
|
|
475
|
+
|
|
476
|
+
**What Happens**:
|
|
477
|
+
- Workflow execution stops
|
|
478
|
+
- Error: "Cannot read property 'X' of undefined"
|
|
479
|
+
- Error: "Cannot read property 'X' of null"
|
|
480
|
+
- Crashes on missing data
|
|
481
|
+
|
|
482
|
+
### The Problem
|
|
483
|
+
|
|
484
|
+
```javascript
|
|
485
|
+
// ❌ WRONG: No null check - crashes if user doesn't exist
|
|
486
|
+
const email = item.json.user.email;
|
|
487
|
+
```
|
|
488
|
+
|
|
489
|
+
```javascript
|
|
490
|
+
// ❌ WRONG: Assumes array has items
|
|
491
|
+
const firstItem = $input.all()[0].json;
|
|
492
|
+
```
|
|
493
|
+
|
|
494
|
+
```javascript
|
|
495
|
+
// ❌ WRONG: Assumes nested property exists
|
|
496
|
+
const city = $json.address.city;
|
|
497
|
+
```
|
|
498
|
+
|
|
499
|
+
```javascript
|
|
500
|
+
// ❌ WRONG: No validation before array operations
|
|
501
|
+
const names = $json.users.map(user => user.name);
|
|
502
|
+
```
|
|
503
|
+
|
|
504
|
+
### The Solution
|
|
505
|
+
|
|
506
|
+
```javascript
|
|
507
|
+
// ✅ CORRECT: Optional chaining
|
|
508
|
+
const email = item.json?.user?.email || 'no-email@example.com';
|
|
509
|
+
```
|
|
510
|
+
|
|
511
|
+
```javascript
|
|
512
|
+
// ✅ CORRECT: Check array length
|
|
513
|
+
const items = $input.all();
|
|
514
|
+
|
|
515
|
+
if (items.length === 0) {
|
|
516
|
+
return [];
|
|
517
|
+
}
|
|
518
|
+
|
|
519
|
+
const firstItem = items[0].json;
|
|
520
|
+
```
|
|
521
|
+
|
|
522
|
+
```javascript
|
|
523
|
+
// ✅ CORRECT: Guard clauses
|
|
524
|
+
const data = $input.first().json;
|
|
525
|
+
|
|
526
|
+
if (!data.address) {
|
|
527
|
+
return [{json: {error: 'No address provided'}}];
|
|
528
|
+
}
|
|
529
|
+
|
|
530
|
+
const city = data.address.city;
|
|
531
|
+
```
|
|
532
|
+
|
|
533
|
+
```javascript
|
|
534
|
+
// ✅ CORRECT: Default values
|
|
535
|
+
const users = $json.users || [];
|
|
536
|
+
const names = users.map(user => user.name || 'Unknown');
|
|
537
|
+
```
|
|
538
|
+
|
|
539
|
+
```javascript
|
|
540
|
+
// ✅ CORRECT: Try-catch for risky operations
|
|
541
|
+
try {
|
|
542
|
+
const email = item.json.user.email.toLowerCase();
|
|
543
|
+
return [{json: {email}}];
|
|
544
|
+
} catch (error) {
|
|
545
|
+
return [{
|
|
546
|
+
json: {
|
|
547
|
+
error: 'Invalid user data',
|
|
548
|
+
details: error.message
|
|
549
|
+
}
|
|
550
|
+
}];
|
|
551
|
+
}
|
|
552
|
+
```
|
|
553
|
+
|
|
554
|
+
### Safe Access Patterns
|
|
555
|
+
|
|
556
|
+
```javascript
|
|
557
|
+
// Pattern 1: Optional chaining (modern, recommended)
|
|
558
|
+
const value = data?.nested?.property?.value;
|
|
559
|
+
|
|
560
|
+
// Pattern 2: Logical OR with default
|
|
561
|
+
const value = data.property || 'default';
|
|
562
|
+
|
|
563
|
+
// Pattern 3: Ternary check
|
|
564
|
+
const value = data.property ? data.property : 'default';
|
|
565
|
+
|
|
566
|
+
// Pattern 4: Guard clause
|
|
567
|
+
if (!data.property) {
|
|
568
|
+
return [];
|
|
569
|
+
}
|
|
570
|
+
const value = data.property;
|
|
571
|
+
|
|
572
|
+
// Pattern 5: Try-catch
|
|
573
|
+
try {
|
|
574
|
+
const value = data.nested.property.value;
|
|
575
|
+
} catch (error) {
|
|
576
|
+
const value = 'default';
|
|
577
|
+
}
|
|
578
|
+
```
|
|
579
|
+
|
|
580
|
+
### Webhook Data Safety
|
|
581
|
+
|
|
582
|
+
```javascript
|
|
583
|
+
// Webhook data requires extra safety
|
|
584
|
+
|
|
585
|
+
// ❌ RISKY: Assumes all fields exist
|
|
586
|
+
const name = $json.body.user.name;
|
|
587
|
+
const email = $json.body.user.email;
|
|
588
|
+
|
|
589
|
+
// ✅ SAFE: Check each level
|
|
590
|
+
const body = $json.body || {};
|
|
591
|
+
const user = body.user || {};
|
|
592
|
+
const name = user.name || 'Unknown';
|
|
593
|
+
const email = user.email || 'no-email';
|
|
594
|
+
|
|
595
|
+
// ✅ BETTER: Optional chaining
|
|
596
|
+
const name = $json.body?.user?.name || 'Unknown';
|
|
597
|
+
const email = $json.body?.user?.email || 'no-email';
|
|
598
|
+
```
|
|
599
|
+
|
|
600
|
+
### Array Safety
|
|
601
|
+
|
|
602
|
+
```javascript
|
|
603
|
+
// ❌ RISKY: No length check
|
|
604
|
+
const items = $input.all();
|
|
605
|
+
const firstId = items[0].json.id;
|
|
606
|
+
|
|
607
|
+
// ✅ SAFE: Check length
|
|
608
|
+
const items = $input.all();
|
|
609
|
+
|
|
610
|
+
if (items.length > 0) {
|
|
611
|
+
const firstId = items[0].json.id;
|
|
612
|
+
} else {
|
|
613
|
+
// Handle empty case
|
|
614
|
+
return [];
|
|
615
|
+
}
|
|
616
|
+
|
|
617
|
+
// ✅ BETTER: Use $input.first()
|
|
618
|
+
const firstItem = $input.first();
|
|
619
|
+
const firstId = firstItem.json.id; // Built-in safety
|
|
620
|
+
```
|
|
621
|
+
|
|
622
|
+
### Object Property Safety
|
|
623
|
+
|
|
624
|
+
```javascript
|
|
625
|
+
// ❌ RISKY: Direct access
|
|
626
|
+
const config = $json.settings.advanced.timeout;
|
|
627
|
+
|
|
628
|
+
// ✅ SAFE: Step by step with defaults
|
|
629
|
+
const settings = $json.settings || {};
|
|
630
|
+
const advanced = settings.advanced || {};
|
|
631
|
+
const timeout = advanced.timeout || 30000;
|
|
632
|
+
|
|
633
|
+
// ✅ BETTER: Optional chaining
|
|
634
|
+
const timeout = $json.settings?.advanced?.timeout ?? 30000;
|
|
635
|
+
// Note: ?? (nullish coalescing) vs || (logical OR)
|
|
636
|
+
```
|
|
637
|
+
|
|
638
|
+
---
|
|
639
|
+
|
|
640
|
+
## Error Prevention Checklist
|
|
641
|
+
|
|
642
|
+
Use this checklist before deploying Code nodes:
|
|
643
|
+
|
|
644
|
+
### Code Structure
|
|
645
|
+
- [ ] Code field is not empty
|
|
646
|
+
- [ ] Return statement exists
|
|
647
|
+
- [ ] All code paths return data
|
|
648
|
+
|
|
649
|
+
### Return Format
|
|
650
|
+
- [ ] Returns array: `[...]`
|
|
651
|
+
- [ ] Each item has `json` property: `{json: {...}}`
|
|
652
|
+
- [ ] Format is `[{json: {...}}]`
|
|
653
|
+
|
|
654
|
+
### Syntax
|
|
655
|
+
- [ ] No `{{ }}` expression syntax (use JavaScript)
|
|
656
|
+
- [ ] Template literals use backticks: `` `${variable}` ``
|
|
657
|
+
- [ ] All quotes and brackets balanced
|
|
658
|
+
- [ ] Strings properly escaped
|
|
659
|
+
|
|
660
|
+
### Data Safety
|
|
661
|
+
- [ ] Null checks for optional properties
|
|
662
|
+
- [ ] Array length checks before access
|
|
663
|
+
- [ ] Webhook data accessed via `.body`
|
|
664
|
+
- [ ] Try-catch for risky operations
|
|
665
|
+
- [ ] Default values for missing data
|
|
666
|
+
|
|
667
|
+
### Testing
|
|
668
|
+
- [ ] Test with empty input
|
|
669
|
+
- [ ] Test with missing fields
|
|
670
|
+
- [ ] Test with unexpected data types
|
|
671
|
+
- [ ] Check browser console for errors
|
|
672
|
+
|
|
673
|
+
---
|
|
674
|
+
|
|
675
|
+
## Quick Error Reference
|
|
676
|
+
|
|
677
|
+
| Error Message | Likely Cause | Fix |
|
|
678
|
+
|---------------|--------------|-----|
|
|
679
|
+
| "Code cannot be empty" | Empty code field | Add meaningful code |
|
|
680
|
+
| "Code must return data" | Missing return statement | Add `return [...]` |
|
|
681
|
+
| "Return value must be an array" | Returning object instead of array | Wrap in `[...]` |
|
|
682
|
+
| "Each item must have json property" | Missing `json` wrapper | Use `{json: {...}}` |
|
|
683
|
+
| "Unexpected token" | Expression syntax `{{ }}` in code | Remove `{{ }}`, use JavaScript |
|
|
684
|
+
| "Cannot read property X of undefined" | Missing null check | Use optional chaining `?.` |
|
|
685
|
+
| "Cannot read property X of null" | Null value access | Add guard clause or default |
|
|
686
|
+
| "Unmatched expression brackets" | Quote/bracket imbalance | Check string escaping |
|
|
687
|
+
|
|
688
|
+
---
|
|
689
|
+
|
|
690
|
+
## Debugging Tips
|
|
691
|
+
|
|
692
|
+
### 1. Use console.log()
|
|
693
|
+
|
|
694
|
+
```javascript
|
|
695
|
+
const items = $input.all();
|
|
696
|
+
console.log('Items count:', items.length);
|
|
697
|
+
console.log('First item:', items[0]);
|
|
698
|
+
|
|
699
|
+
// Check browser console (F12) for output
|
|
700
|
+
```
|
|
701
|
+
|
|
702
|
+
### 2. Return Intermediate Results
|
|
703
|
+
|
|
704
|
+
```javascript
|
|
705
|
+
// Debug by returning current state
|
|
706
|
+
const items = $input.all();
|
|
707
|
+
const processed = items.map(item => ({json: item.json}));
|
|
708
|
+
|
|
709
|
+
// Return to see what you have
|
|
710
|
+
return processed;
|
|
711
|
+
```
|
|
712
|
+
|
|
713
|
+
### 3. Try-Catch for Troubleshooting
|
|
714
|
+
|
|
715
|
+
```javascript
|
|
716
|
+
try {
|
|
717
|
+
// Your code here
|
|
718
|
+
const result = riskyOperation();
|
|
719
|
+
return [{json: {result}}];
|
|
720
|
+
} catch (error) {
|
|
721
|
+
// See what failed
|
|
722
|
+
return [{
|
|
723
|
+
json: {
|
|
724
|
+
error: error.message,
|
|
725
|
+
stack: error.stack
|
|
726
|
+
}
|
|
727
|
+
}];
|
|
728
|
+
}
|
|
729
|
+
```
|
|
730
|
+
|
|
731
|
+
### 4. Validate Input Structure
|
|
732
|
+
|
|
733
|
+
```javascript
|
|
734
|
+
const items = $input.all();
|
|
735
|
+
|
|
736
|
+
// Check what you received
|
|
737
|
+
console.log('Input structure:', JSON.stringify(items[0], null, 2));
|
|
738
|
+
|
|
739
|
+
// Then process
|
|
740
|
+
```
|
|
741
|
+
|
|
742
|
+
---
|
|
743
|
+
|
|
744
|
+
## Summary
|
|
745
|
+
|
|
746
|
+
**Top 5 Errors to Avoid**:
|
|
747
|
+
1. **Empty code / missing return** (38%) - Always return data
|
|
748
|
+
2. **Expression syntax `{{ }}`** (8%) - Use JavaScript, not expressions
|
|
749
|
+
3. **Wrong return format** (5%) - Always `[{json: {...}}]`
|
|
750
|
+
4. **Unmatched brackets** (6%) - Escape strings properly
|
|
751
|
+
5. **Missing null checks** - Use optional chaining `?.`
|
|
752
|
+
|
|
753
|
+
**Quick Prevention**:
|
|
754
|
+
- Return `[{json: {...}}]` format
|
|
755
|
+
- Use JavaScript, NOT `{{ }}` expressions
|
|
756
|
+
- Check for null/undefined before accessing
|
|
757
|
+
- Test with empty and invalid data
|
|
758
|
+
- Use browser console for debugging
|
|
759
|
+
|
|
760
|
+
**See Also**:
|
|
761
|
+
- [SKILL.md](SKILL.md) - Overview and best practices
|
|
762
|
+
- [DATA_ACCESS.md](DATA_ACCESS.md) - Safe data access patterns
|
|
763
|
+
- [COMMON_PATTERNS.md](COMMON_PATTERNS.md) - Working examples
|