kestra-io/kestra · error · PebbleException

The 'flatten' filter can only be applied to lists.

Error message

The 'flatten' filter can only be applied to lists.

What it means

Thrown by the FlattenFilter when the input is not null but is not a List. The flatten filter collapses one level of nested lists into a single flat list; it cannot operate on strings, maps, numbers, or other non-list types.

Source

Thrown at core/src/main/java/io/kestra/core/runners/pebble/filters/FlattenFilter.java:28

import io.pebbletemplates.pebble.template.EvaluationContext;
import io.pebbletemplates.pebble.template.PebbleTemplate;

public class FlattenFilter implements Filter {
    private final List<String> argumentNames = new ArrayList<>();

    @Override
    public List<String> getArgumentNames() {
        return this.argumentNames;
    }

    @Override
    public Object apply(Object input, Map<String, Object> args, PebbleTemplate self, EvaluationContext context, int lineNumber) throws PebbleException {
        if (input == null) {
            return null;
        }

        if (!(input instanceof List)) {
            throw new PebbleException(null, "The 'flatten' filter can only be applied to lists.", lineNumber, self.getName());
        }

        try {
            List<?> list = (List<?>) input;
            List<Object> flattened = list.stream()
                .flatMap(o -> o instanceof List<?> listValue ? listValue.stream() : Stream.of(o))
                .toList();
            return flattened;
        } catch (Exception e) {
            throw new PebbleException(e, "An error occurred while flattening the list.", lineNumber, self.getName());
        }
    }
}

View on GitHub (pinned to 823fada927)

Solutions

  1. Ensure the input is a list before calling flatten.
  2. Wrap non-list values: '{{ [myvalue] | flatten }}'.
  3. Add a type check or conditional to only apply flatten when the value is a list.

Example fix

{# before #}
{{ outputs.task.value | flatten }}
{# outputs.task.value is a map #}

{# after — ensure list #}
{{ [outputs.task.value] | flatten }}
Defensive patterns

Strategy: type-guard

Validate before calling

{# Ensure the input is a list before calling flatten #}
{% set input = outputs.task.value %}
{% if input is iterable %}
  {{ input | flatten }}
{% else %}
  {{ [input] | flatten }}
{% endif %}

Type guard

{# Pebble 'is iterable' narrows to list-like types #}
{% if myvar is iterable %}
  {{ myvar | flatten }}
{% endif %}

Prevention

When it happens

Trigger: Calling flatten on a non-list value: '{{ mystring | flatten }}', '{{ mymap | flatten }}', '{{ 42 | flatten }}'. The input variable resolves to a type other than List at runtime.

Common situations: A task output that is sometimes a list of lists and sometimes a single value or string. Passing a JSON object where a JSON array was expected. Template logic that assumes nested-list structure from an output that is not guaranteed to be a list.

Related errors


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