A plain {{steps.<step_id>.result...}} placeholder is inserted as text:
Objects and arrays become JSON
Strings are inserted as-is, without quotes
null or a missing value becomes an empty string
This automatic conversion applies only to steps.<step_id>.result... placeholders with no filter. Other objects, such as {{item}} when the item is an object, render as [object Object]; write {{item | json}} instead.A step that reads another step’s result must list that step in needs, or it may run before the result exists. See Step Module Options.
PYTHON_SANDBOX_RUN returns its output under result.data, so a later step reads it as {{steps.<step_id>.result.data}}.
# String manipulation{{ variable | upper }}{{ variable | lower }}{{ variable | trim }}{{ variable | replace('old', 'new') }}# Default values{{ variable | default('fallback_value') }}# JSON handling{{ data | json }}# List operations{{ items | first }}{{ items | last }}{{ items | join(', ') }}
default replaces only a missing value. To also replace null, an empty string or false, write default('fallback_value', true).json is added by Jinba Flow and outputs strict JSON: strings keep their quotes and null stays null. There is no tojson filter.Jinba Flow also adds filters for the output of a forEach step:
The Python examples below read earlier results with json.loads(r'''{{steps.<step_id>.result}}'''). Pasting a result straight into Python code breaks on JSON values such as null, true and false. PYTHON_SANDBOX_RUN uses the value of the last line as its result; set data_type to OBJECT and end with json.dumps(...) to return structured data.
Nunjucks does not support Jinja2’s {% for x in list if condition %}: it checks the condition once for the whole list, so the loop usually outputs nothing. Put the condition inside the loop instead:
value: | {%- for entry in steps.get_items.result %} {%- if entry.status == 'active' %} - {{entry.name}} {%- endif %} {%- endfor %}
Verify the property path is correct (for PYTHON_SANDBOX_RUN, the output is under result.data)
Template syntax error
Check for balanced braces {{ }}
Verify Nunjucks tag syntax {% %}
Look for missing quotes in strings
Unexpected output
Use debug steps to inspect intermediate values
Check whitespace handling
Verify data types (string vs object)
[object Object] means an object was inserted without conversion; add | json
TemplateSecurityError: ... is not allowed in templates
Templates are flow-authored, so the engine refuses anything that could run code or read files, and the step fails instead of rendering
Not allowed: reading constructor, prototype or __proto__ on any value (including a result field with that name); {% asyncEach %} / {% asyncAll %}; names that are not plain identifiers (letters, digits, _, $) as a variable, loop variable, macro, filter or test
{% include %}, {% import %} and {% extends %} fail separately with a “template not found” render error, because no template files are loadable from a flow
Ordinary member access, method calls on values such as {{ steps.x.result.trim() }}, filters, range and macros keep working
Front-end code with its own {{ }} interpolation (for example {{ user?.name }} in an HTML snippet) must be wrapped in {% raw %} ... {% endraw %}