twigphp/Twig · error · RuntimeError
The "batch" filter expects a sequence or a mapping, got
Error message
The "batch" filter expects a sequence or a mapping, got "%s".
What it means
CoreExtension::batch() implements the `batch` Twig filter, which chunks a sequence/mapping into groups of a given size. It throws this RuntimeError when the input is not iterable (e.g. a string, int, null, or object without Traversable), because array_chunk/toArray require array-like input. The message includes the actual debug type of the received value.
Solutions
- Ensure the variable passed to `|batch` is an array or Traversable before the filter
- Default the value in the template: `{{ (items ?? [])|batch(3) }}`
- Fix the data source so it always returns an array (e.g. `$repo->findAll() ?? []`)
- Check for null/empty upstream and skip rendering the batch block with `{% if items is iterable %}`
Example fix
// before (Twig template)
{% for group in items|batch(3) %}...
// after
{% for group in (items ?? [])|batch(3) %}... Defensive patterns
Strategy: type-guard
Validate before calling
// PHP, before passing a variable destined for |batch to the template
if (!is_iterable($items)) { $items = []; }
$template->render(['items' => $items]); Type guard
function isBatchable(mixed $items): bool
{
return is_iterable($items);
} Try / catch
try {
$html = $twig->render('tpl.html.twig', ['items' => $items]);
} catch (\Twig\Error\RuntimeError $e) {
if (!str_contains($e->getMessage(), '"batch" filter expects')) { throw $e; }
$html = $twig->render('tpl.html.twig', ['items' => []]);
} Prevention
- Coalesce nullable collections before rendering: `items ?? []`
- Type-hint controller/service return values as array or Collection
- Assert repository methods never return null for list queries
- Add template integration tests covering empty and non-iterable inputs
When it happens
Trigger: `{{ value|batch(3) }}` where value is a string, number, boolean, or null; passing a single entity instead of a collection; a repository/finder method that returned null on failure and the template pipes it to batch without a null check.
Common situations: Controller passes null to the template when a query finds nothing; a service returns a scalar where a collection was expected; refactor changed a variable from array to string; Doctrine returning null instead of an array.
Understand the failure class
Background: Type mismatch errors: IllegalArgumentException, TypeError and type guards across 150 open-source libraries — this error's family across 150 libraries.
Related errors
- The "column" filter expects a sequence or a mapping, got
- The "filter" filter expects a sequence/mapping or…
- The "find" filter expects a sequence or a mapping, got
- The "map" filter expects a sequence or a mapping, got
- The "reduce" filter expects a sequence or a mapping, got
AI-assisted analysis of twigphp/Twig@a414c3a491 (2026-09-13).
Data as JSON: /api/errors/05263256d9571170.
Report an issue: GitHub.
Appendix: source
Thrown at src/Extension/CoreExtension.php:1713
throw new RuntimeError(\sprintf('Constant "%s" is undefined.', $constant));
}
return $checkDefined ? true : \constant($constant);
}
/**
* Batches item.
*
* @param array $items An array of items
* @param int $size The size of the batch
* @param mixed $fill A value used to fill missing items
*
* @internal
*/
public static function batch($items, $size, $fill = null, $preserveKeys = true): array
{
if (!is_iterable($items)) {
throw new RuntimeError(\sprintf('The "batch" filter expects a sequence or a mapping, got "%s".', get_debug_type($items)));
}
$size = (int) ceil($size);
$result = array_chunk(self::toArray($items, $preserveKeys), $size, $preserveKeys);
if (null !== $fill && $result) {
$last = \count($result) - 1;
if ($fillCount = $size - \count($result[$last])) {
for ($i = 0; $i < $fillCount; ++$i) {
$result[$last][] = $fill;
}
}
}
return $result;
}
View on GitHub (pinned to a414c3a491)