{"record":{"id":"069cbdef65680808","repo":"twigphp/Twig","slug":"the-reduce-filter-expects-a-sequence-or-a-mapping-got-s","errorCode":null,"errorMessage":"The \"reduce\" filter expects a sequence or a mapping, got \"%s\".","messagePattern":"The \"reduce\" filter expects a sequence or a mapping, got \"(.+?)\"\\.","errorType":"exception","errorClass":"RuntimeError","httpStatus":null,"severity":"error","filePath":"src/Extension/CoreExtension.php","lineNumber":2122,"sourceCode":"        self::checkArrow($isSandboxed, $arrow, 'map', 'filter');\n\n        $r = [];\n        foreach ($array as $k => $v) {\n            $r[$k] = $arrow($v, $k);\n        }\n\n        return $r;\n    }\n\n    /**\n     * @param \\Closure $arrow\n     *\n     * @internal\n     */\n    public static function reduce(Environment $env, bool $isSandboxed, $array, $arrow, $initial = null)\n    {\n        if (!is_iterable($array)) {\n            throw new RuntimeError(\\sprintf('The \"reduce\" filter expects a sequence or a mapping, got \"%s\".', get_debug_type($array)));\n        }\n\n        self::checkArrow($isSandboxed, $arrow, 'reduce', 'filter');\n\n        $accumulator = $initial;\n        foreach ($array as $key => $value) {\n            $accumulator = $arrow($accumulator, $value, $key);\n        }\n\n        return $accumulator;\n    }\n\n    /**\n     * @param \\Closure $arrow\n     *\n     * @internal\n     */\n    public static function arraySome(Environment $env, $array, $arrow, bool $isSandboxed = false)","sourceCodeStart":2104,"sourceCodeEnd":2140,"githubUrl":"https://github.com/twigphp/Twig/blob/a414c3a491defb5a60f2fc88ef79ff37c90010cd/src/Extension/CoreExtension.php#L2104-L2140","documentation":"The Twig `reduce` filter (CoreExtension::reduce, called via twig_array_reduce) folds an iterable into a single value using an arrow function. Twig throws this RuntimeError when the input is not a sequence or mapping (i.e. `is_iterable()` fails). The check happens at runtime in PHP, so only affected code paths surface it.","triggerScenarios":"`{{ items|reduce((acc, v) => acc + v, 0) }}` where items is null/scalar. Also when a nullable field is passed directly and happens to be null. Guard at CoreExtension.php:2122.","commonSituations":"Aggregating totals over a collection that is missing/null (no rows fetched, optional relation not loaded), config scalars passed into aggregation chains, functions returning null on empty results instead of arrays.","solutions":["Default the input to an empty array: `{{ (items ?? [])|reduce((acc, v) => acc + v, 0) }}`.","Ensure the upstream code always returns an array (e.g. `?? []` in PHP, or fix the repository method).","Branch on `{% if items is iterable %}` when the shape can legitimately differ.","Catch Twig\\Error\\RuntimeError around Template::render to capture the failing template and line."],"exampleFix":"// before (Twig)\n{{ amounts|reduce((carry, a) => carry + a, 0) }}\n\n// after\n{{ (amounts ?? [])|reduce((carry, a) => carry + a, 0) }}","handlingStrategy":"validation","validationCode":"// PHP, before rendering\ndef ensure_iterable_for_reduce($value): void {\n    if (!is_iterable($value)) {\n        throw new InvalidArgumentException('reduce() input must be iterable, got ' . get_debug_type($value));\n    }\n}","typeGuard":"function isIterable($v): bool { return is_array($v) || $v instanceof \\Traversable; }","tryCatchPattern":"try {\n    $html = $twig->render('tpl.html.twig', $context);\n} catch (\\Twig\\Error\\RuntimeError $e) {\n    if (str_contains($e->getMessage(), '\"reduce\" filter expects a sequence or a mapping')) {\n        // use a zero-value default instead\n    } else { throw $e; }\n}","preventionTips":["Provide an explicit `$initial` to reduce so empty arrays still yield a sane result","Default nullable aggregates: `(items ?? [])|reduce(...)`","Enforce collection return types (array) in services feeding templates","Lint templates in CI with realistic empty-state fixtures"],"tags":["twig","filter","type-mismatch","runtime-error"],"backgroundTag":"type-mismatch","analyzedSha":"a414c3a491defb5a60f2fc88ef79ff37c90010cd","analyzedAt":"2026-09-13T15:10:46.849Z","contentChangedAt":"2026-09-13T15:10:46.849Z","schemaVersion":2},"datasetVersion":"2026-09-16T04:17:20.429Z"}