Code block
Run JavaScript in a sandbox as a workflow step, read data from earlier steps and return a value that later steps can reference.
The Code block (type: "code") runs a short JavaScript function in a sandbox and stores what it returns, so later steps can use it. It has no plain-language guide; to map or filter records without writing code, see the Transform block.
When to use it
- Calculate or reshape values that a template reference cannot express, such as summing invoice lines or grouping payments by customer.
- Decode or re-encode base64 file content between steps.
- Prepare a payload for the next step when an integration expects a specific structure.
The sandbox has no network or file access. To call an HTTP API, use the API Request block.
A Code step cannot use workflow secrets. A {{secrets.KEY}} reference anywhere in its config (including input) is refused when the workflow is saved, and a stored workflow that has one fails at run start. Call the API that needs the secret in an API Request step and pass its output to the code step through input.
Configuration
Field (config key) | Editor label | Type | Required | Meaning |
|---|---|---|---|---|
code | Code | string | Yes | The body of an async function. Read input from input and return the result. |
input | Input Data (JSON) | object | No | The value bound to input. Use template references here, such as {"invoices": "{{steps.list_invoices.data}}"}. When empty, input is the run input. |
language | Language | javascript or typescript | No | Default javascript. The sandbox runs the code as JavaScript; type annotations are not compiled away. |
sandbox | Not shown | object | No | Limits: timeoutMs (100 to 30000, default 5000; overrides timeout), maxOutputSize in bytes (1024 to 10485760, default 1048576), memoryLimitMb (16 to 512, default 128). |
allowedLibraries | Not shown | string array | No | Helper libraries exposed as globals. Default ["lodash", "dayjs", "validator"]. uuid and fflate can also be named. |
codeReview | Not shown | boolean | No | Default true. Scans the code before it runs (see Errors and limits). |
timeout | Timeout (ms) | number or numeric text | No | The time limit in milliseconds, up to 30000 (30 s). The editor's default is 30000. Ignored when sandbox.timeoutMs is set. Without either, the limit is 5000. |
What the code can use
input, plus standard JavaScript built-ins such asJSON,Math,Date,Array,Object,Map,Set,RegExpandPromise.atob,btoa,TextEncoder,TextDecoder, typed arrays and abase64helper for converting between base64 text and bytes.- The libraries in
allowedLibraries. These are safe subsets of the named libraries, exposed as globals (lodash.map(...)), not full packages.
console output is not captured by default.
Output
The step stores this object. Reference it as {{steps.<step id>.<field>}}.
| Field | Type | Meaning |
|---|---|---|
result | any | The value your code returned. Read it as {{steps.<step id>.result}} or a path inside it. |
success | boolean | true when the step completed. A failed run of the code fails the step instead (see below). |
metadata | object | Execution details, such as executionTimeMs and the sandbox limits used. |
codeReview | object | The pre-run scan result, when codeReview is on. |
The editor's output list also shows logs; the executor does not return that field.
Example
This workflow lists open Stripe invoices, then totals the amount due per customer.
{
"name": "Open invoice totals by customer",
"trigger": { "type": "api" },
"steps": [
{
"id": "list_invoices",
"type": "action",
"name": "List open invoices",
"action": "stripe.listInvoices",
"config": { "status": "open" }
},
{
"id": "total_by_customer",
"type": "code",
"name": "Total amount due by customer",
"config": {
"language": "javascript",
"input": { "invoices": "{{steps.list_invoices.data}}" },
"code": "const totals = {};\nfor (const inv of input.invoices || []) {\n totals[inv.customer] = (totals[inv.customer] || 0) + inv.amount_due / 100;\n}\nreturn { totals, count: Object.keys(totals).length };",
"sandbox": { "timeoutMs": 10000 }
}
}
]
}A later step reads the totals as {{steps.total_by_customer.result.totals}}.
Errors and limits
- Security scan. With
codeReviewon, the code text (comments excluded) is scanned before it runs, and code that matches a blocked pattern is rejected. Blocked patterns includeeval(,Function,require(,import,process.,globalThis, anyconstructoror__proto__reference, built-in prototypes such asObject.prototype,Reflect.apply, file system calls and network calls such asfetch(. The scan matches text, so a property or string that contains one of these words is rejected too. Comments are ignored, and a method call such as/re/.exec(text)is allowed. The step fails withCode step failed [security]and the matched lines. - Runtime errors. A thrown error fails the step with
Code step failed [runtime]and the error message. - Time limit. Code that runs longer than its limit (
sandbox.timeoutMs, elsetimeout, else 5000 ms) fails the step. The ceiling is 30000 ms (30 s); a higher value is lowered to it, and 0 or a negative value is raised to 100 ms. - Output size. A returned value larger than
sandbox.maxOutputSizeas JSON fails the step withCode step failed [output_size]. Return only the fields later steps need, or raise the limit up to 10 MiB. - Use
errorHandlingon the step to continue or retry after a failure. See Errors, retries and timeouts.
Loopfour