kestra-io/kestra · error · PebbleException

'keys' filter can only be applied to List, Map, Array. Actua

Error message

'keys' filter can only be applied to List, Map, Array. Actual type was: {}

What it means

Thrown by the 'keys' Pebble filter when the input is not a Map, List, or Java array. The filter dispatches on these three types and falls back to this error for anything else (String, Number, Boolean, or null-safe non-collections). The message reports the actual Java class so the caller can see what was passed.

Source

Thrown at core/src/main/java/io/kestra/core/runners/pebble/filters/KeysFilter.java:45

            return inputMap.keySet();
        }

        if (input instanceof List inputList) {
            return IntStream
                .rangeClosed(0, inputList.size() - 1)
                .boxed()
                .toList();
        }

        if (input.getClass().isArray()) {
            int length = Array.getLength(input);
            return IntStream
                .rangeClosed(0, length - 1)
                .boxed()
                .toList();
        }

        throw new PebbleException(null, "'keys' filter can only be applied to List, Map, Array. Actual type was: " + input.getClass().getName(), lineNumber, self.getName());

    }
}

View on GitHub (pinned to 823fada927)

Solutions

  1. Parse the input first: `{{ outputs.fetch.body | json | keys }}` if the body is a JSON string.
  2. Confirm the variable is actually a Map by printing it (`{{ myvar }}`) before applying `keys`.
  3. Switch to a filter that matches the actual type (e.g. `length` for strings).

Example fix

# before
{{ outputs.api.body | keys }}
# after
{{ outputs.api.body | json | keys }}
Defensive patterns

Strategy: type-guard

Validate before calling

# Ensure the input is a Map/List before calling keys:
{% if myvar is iterable and myvar is not string %}
  {{ myvar | keys }}
{% else %}
  []
{% endif %}

Type guard

# Pebble narrowing: `is iterable` excludes scalars; pair with `is not string`
# to avoid treating a String as an iterable of chars.

Prevention

When it happens

Trigger: Calling `keys` on a scalar variable: `{{ myString | keys }}`, `{{ 42 | keys }}`, `{{ true | keys }}`. Also when a task output that was expected to be a Map resolves to a scalar (e.g. a JSON string instead of a parsed object).

Common situations: Forgetting to parse JSON before calling keys; an upstream task returning a different shape than expected after a plugin version change; misreading the output spec.

Related errors


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