kestra-io/kestra · error · PebbleException

The 'loopOutputs' function expects a non-null argument 'outp

Error message

The 'loopOutputs' function expects a non-null argument 'outputs'.

What it means

The loopOutputs(outputs, name) Pebble function requires a non-null 'outputs' argument. This argument should be a reference to a Loop task's iteration list (e.g. outputs.myLoop.outputs). If the argument is absent or resolves to null, the function cannot iterate and throws immediately.

Source

Thrown at core/src/main/java/io/kestra/core/runners/pebble/functions/LoopOutputsFunction.java:39

        ARG_OUTPUTS, "outputs.myLoop.outputs",
        ARG_NAME, "'myOutputName'"
    );

    @Override
    public List<String> getArgumentNames() {
        return ARGUMENT_NAMES;
    }

    @Override
    public Map<String, String> getArgumentDefaults() {
        return ARGUMENT_DEFAULTS;
    }

    @Override
    public Object execute(Map<String, Object> args, PebbleTemplate self, EvaluationContext context, int lineNumber) {
        Object outputsArg = args.get(ARG_OUTPUTS);
        if (outputsArg == null) {
            throw new PebbleException(null, "The 'loopOutputs' function expects a non-null argument 'outputs'.", lineNumber, self.getName());
        }
        if (!(outputsArg instanceof List<?>)) {
            throw new PebbleException(null, "The 'loopOutputs' function expects 'outputs' to be a list.", lineNumber, self.getName());
        }

        Object nameArg = args.get(ARG_NAME);
        if (nameArg == null) {
            throw new PebbleException(null, "The 'loopOutputs' function expects a non-null argument 'name'.", lineNumber, self.getName());
        }
        if (!(nameArg instanceof String)) {
            throw new PebbleException(null, "The 'loopOutputs' function expects 'name' to be a string.", lineNumber, self.getName());
        }

        String key = (String) nameArg;
        List<?> loopOutputs = (List<?>) outputsArg;
        List<Object> result = new ArrayList<>(loopOutputs.size());

        for (Object loopOutputObj : loopOutputs) {

View on GitHub (pinned to 823fada927)

Solutions

  1. Provide a valid outputs reference from a Loop task: {{ loopOutputs(outputs.myLoop.outputs, 'myOutput') }}.
  2. Verify the Loop task ID matches the reference exactly.
  3. If the loop may have zero iterations, guard with a null check: {% if outputs.myLoop.outputs is not null %}{{ loopOutputs(outputs.myLoop.outputs, 'myOutput') }}{% endif %}.

Example fix

# before
value: "{{ loopOutputs(name='result') }}"
# after
value: "{{ loopOutputs(outputs.myLoop.outputs, 'result') }}"
Defensive patterns

Strategy: validation

Validate before calling

# Guard against null outputs before calling loopOutputs:
{% if outputs.myLoop.outputs is not null %}
  {{ loopOutputs(outputs.myLoop.outputs, 'myOutput') }}
{% else %}
  []
{% endif %}

Prevention

When it happens

Trigger: Calling {{ loopOutputs() }} with no arguments. Calling {{ loopOutputs(name='myOutput') }} without the outputs argument. Referencing a loop task ID that does not exist or whose outputs are null (e.g. the loop task has not executed yet).

Common situations: The flow author misspells the loop task ID in the outputs reference. The loop task has no iterations (empty for-each), so its outputs are null. The function is called outside the context of a Loop task.

Related errors


AI-assisted analysis of kestra-io/kestra@823fada927 (2026-08-14). Data as JSON: /api/errors/5f37501b10b08c0a. Report an issue: GitHub.