{"record":{"id":"8fa4b02d27ddeb43","repo":"kestra-io/kestra","slug":"unknown-value-type","errorCode":null,"errorMessage":"Unknown value type: {}","messagePattern":"Unknown value type: (.+?)","errorType":"exception","errorClass":"IllegalVariableEvaluationException","httpStatus":null,"severity":"error","filePath":"core/src/main/java/io/kestra/core/runners/FlowableUtils.java","lineNumber":450,"sourceCode":"                                    throw new IllegalVariableEvaluationException(\n                                        \"Found a null value inside the iteration values=\" + serializeAsString(values)\n                                    );\n                                } else {\n                                    return serializeAsString(obj);\n                                }\n                            }))\n                            .distinct()\n                            .toList();\n                        return Either.left(resolvedValues);\n                    } else if (valuesNode.isObject()) {\n                        List<Pair<String, String>> resolvedValues = new ArrayList<>();\n                        Map<String, Object> mapValues = MAPPER.convertValue(valuesNode, JacksonMapper.MAP_TYPE_REFERENCE);\n                        for (var entry : mapValues.entrySet()) {\n                            resolvedValues.add(Pair.of(entry.getKey(), valueAsString(runContext, values, entry.getValue())));\n                        }\n                        return Either.right(resolvedValues);\n                    } else {\n                        throw new IllegalVariableEvaluationException(\"Unknown value type: \" + valuesNode.getNodeType());\n                    }\n                } catch (IOException e) {\n                    throw new IllegalVariableEvaluationException(e);\n                }\n            }\n            case List<?> listValue -> {\n                List<String> resolvedValues = new ArrayList<>(listValue.size());\n                for (Object obj : listValue) {\n                    resolvedValues.add(valueAsString(runContext, values, obj));\n                }\n                return Either.left(resolvedValues.stream().distinct().toList());\n            }\n            case Map<?, ?> mapValue -> {\n                List<Pair<String, String>> resolvedValues = new ArrayList<>();\n                for (var entry : ((Map<String, Object>) mapValue).entrySet()) {\n                    resolvedValues.add(Pair.of(entry.getKey(), valueAsString(runContext, values, entry.getValue())));\n                }\n                return Either.right(resolvedValues);","sourceCodeStart":432,"sourceCodeEnd":468,"githubUrl":"https://github.com/kestra-io/kestra/blob/823fada9274c4f9c251ea0a516460a4f7d958032/core/src/main/java/io/kestra/core/runners/FlowableUtils.java#L432-L468","documentation":"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`).","triggerScenarios":"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\\\"\"`.","commonSituations":"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.","solutions":["Ensure the `values` expression renders to a JSON array or object: wrap a scalar in brackets `\"[{{ outputs.task.value }}]\"`.","Fix the upstream output/jq to return a collection.","If iterating key/value pairs, render a JSON object instead of a scalar."],"exampleFix":"# before — renders to a scalar number\nvalues: \"{{ outputs.compute.count }}\"\n\n# after — wrap into an array\nvalues: \"[{{ outputs.compute.count }}]\"","handlingStrategy":"validation","validationCode":"// Ensure rendered values is a JSON array or object\nString rendered = runContext.render(valuesExpr);\nJsonNode node = MAPPER.readTree(rendered);\nif (!node.isArray() && !node.isObject()) {\n    // wrap scalar into an array\n    rendered = \"[\" + rendered + \"]\";\n}\nvalues = rendered;","typeGuard":null,"tryCatchPattern":"try { FlowableUtils.resolveValues(runContext, values); }\ncatch (IllegalVariableEvaluationException e) {\n    if (e.getMessage().startsWith(\"Unknown value type: \")) {\n        throw new IllegalVariableEvaluationException(\n            \"Iteration 'values' must render to a JSON array or object, got: \" + e.getMessage());\n    } throw e;\n}","preventionTips":["Always render `values` to a JSON array literal `[...]` or object `{...}`.","Double-check jq/Pebble filters return collections, not scalars.","Log the rendered value at DEBUG during development to confirm its shape."],"tags":["iteration","json","scalar","flowable"],"backgroundTag":null,"analyzedSha":"823fada9274c4f9c251ea0a516460a4f7d958032","analyzedAt":"2026-08-14T06:15:17.947Z","schemaVersion":2},"datasetVersion":"2026-08-14T10:17:34.591Z"}