kestra-io/kestra · error · IllegalVariableEvaluationException

Unknown value type: {}

Error message

Unknown value type: {}

What it means

Thrown by `resolveValues` when `values` is a String that renders to valid JSON but the root node is neither an array nor an object — i.e. a scalar JSON value (number, boolean, string, or null). Iteration requires a collection; a bare scalar is not iterable. The placeholder is the Jackson `JsonNodeType` (e.g. `NUMBER`, `BOOLEAN`, `STRING`).

Source

Thrown at core/src/main/java/io/kestra/core/runners/FlowableUtils.java:450

                                    throw new IllegalVariableEvaluationException(
                                        "Found a null value inside the iteration values=" + serializeAsString(values)
                                    );
                                } else {
                                    return serializeAsString(obj);
                                }
                            }))
                            .distinct()
                            .toList();
                        return Either.left(resolvedValues);
                    } else if (valuesNode.isObject()) {
                        List<Pair<String, String>> resolvedValues = new ArrayList<>();
                        Map<String, Object> mapValues = MAPPER.convertValue(valuesNode, JacksonMapper.MAP_TYPE_REFERENCE);
                        for (var entry : mapValues.entrySet()) {
                            resolvedValues.add(Pair.of(entry.getKey(), valueAsString(runContext, values, entry.getValue())));
                        }
                        return Either.right(resolvedValues);
                    } else {
                        throw new IllegalVariableEvaluationException("Unknown value type: " + valuesNode.getNodeType());
                    }
                } catch (IOException e) {
                    throw new IllegalVariableEvaluationException(e);
                }
            }
            case List<?> listValue -> {
                List<String> resolvedValues = new ArrayList<>(listValue.size());
                for (Object obj : listValue) {
                    resolvedValues.add(valueAsString(runContext, values, obj));
                }
                return Either.left(resolvedValues.stream().distinct().toList());
            }
            case Map<?, ?> mapValue -> {
                List<Pair<String, String>> resolvedValues = new ArrayList<>();
                for (var entry : ((Map<String, Object>) mapValue).entrySet()) {
                    resolvedValues.add(Pair.of(entry.getKey(), valueAsString(runContext, values, entry.getValue())));
                }
                return Either.right(resolvedValues);

View on GitHub (pinned to 823fada927)

Solutions

  1. Ensure the `values` expression renders to a JSON array or object: wrap a scalar in brackets `"[{{ outputs.task.value }}]"`.
  2. Fix the upstream output/jq to return a collection.
  3. If iterating key/value pairs, render a JSON object instead of a scalar.

Example fix

# before — renders to a scalar number
values: "{{ outputs.compute.count }}"

# after — wrap into an array
values: "[{{ outputs.compute.count }}]"
Defensive patterns

Strategy: validation

Validate before calling

// Ensure rendered values is a JSON array or object
String rendered = runContext.render(valuesExpr);
JsonNode node = MAPPER.readTree(rendered);
if (!node.isArray() && !node.isObject()) {
    // wrap scalar into an array
    rendered = "[" + rendered + "]";
}
values = rendered;

Try / catch

try { FlowableUtils.resolveValues(runContext, values); }
catch (IllegalVariableEvaluationException e) {
    if (e.getMessage().startsWith("Unknown value type: ")) {
        throw new IllegalVariableEvaluationException(
            "Iteration 'values' must render to a JSON array or object, got: " + e.getMessage());
    } throw e;
}

Prevention

When it happens

Trigger: A ForEach/Loop `values` Pebble expression that renders to a single scalar, e.g. `"{{ outputs.task.value }}"` where `value` is `42` or `true` or a bare word, rather than a JSON array/object. Also triggered when a rendered string is a quoted JSON string `"\"hello\""`.

Common situations: Pointing `values` at a single output instead of a list output; a Pebble expression that returns the first element rather than the whole collection; a misconfigured `jq` filter that selects a scalar field instead of an array.

Related errors


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