twigphp/Twig · error · RuntimeError
The "cycle" function expects a non-empty sequence.
Error message
The "cycle" function expects a non-empty sequence.
What it means
CoreExtension::cycle throws this Twig\RuntimeError when the cycle() function receives an empty sequence (array/Traversable that toArray()-ed to 0 items). cycle($values, $position) needs at least one element to index into, so count($values) === 0 is rejected before computing $values[$position % $count].
Solutions
- Ensure the sequence passed to cycle has at least one element; provide defaults, e.g. cycle(values|default(['a','b']), i).
- Guard the loop: only call cycle when the collection is non-empty (or rely on a for loop that skips empty sets).
- If the value may be null, coalesce first: cycle(someArray ?? ['odd','even'], loop.index0).
- Check upstream data-fetching logic that unexpectedly yields an empty array.
Example fix
// before (Twig)
<tr class="{{ cycle(['odd', 'even'], loop.index0) }}">
// after
<tr class="{{ cycle(colors|default(['odd', 'even']), loop.index0) }}"> Defensive patterns
Strategy: type-guard
Validate before calling
// PHP caller-side guard before rendering with cycle()
function safeCycle(array $values, int $position, array $fallback = ['odd', 'even']): string {
return $values !== [] ? $values[$position % count($values)] : $fallback[$position % count($fallback)];
} Type guard
function isNonEmptyList($v): bool { return is_array($v) && $v !== []; } Try / catch
try {
$html = $twig->render('table.html.twig', ['rows' => $rows]);
} catch (\Twig\Error\RuntimeError $e) {
if (str_contains($e->getMessage(), '"cycle" function expects a non-empty sequence')) {
$html = $twig->render('table.html.twig', ['rows' => $rows, 'colors' => ['odd', 'even']]);
} else { throw $e; }
} Prevention
- Never pass raw query results to cycle(); pipe through |default(['a','b']).
- Prefer using loop.index-based CSS like {{ loop.index is odd ? 'odd' : 'even' }} which cannot fail on empty arrays.
- Check collections for emptiness before looping/striping rows.
- Coerce nullable variables with ?? before passing to cycle().
When it happens
Trigger: Calling {{ cycle(rows, loop.index0) }} or twig_cycle($values, $i) where $values is [] (or an empty Traversable, or a scalar that is not a string and toArray()'s to nothing), regardless of the position argument.
Common situations: Alternating row colors on a table whose data array is empty because a query returned no rows; passing a nullable variable that defaults to [] instead of the intended pair ['odd','even']; passing null (after toArray coercion) to cycle inside a loop.
Understand the failure class
Background: "must not be empty", "cannot be empty" — required-field validation errors across open-source libraries — this error's family across 41 libraries.
Related errors
- The "random" function cannot pick from an empty sequence or…
- Failed to load Twig template
- Regexp " " passed to "matches" failed: .
- Trimming side must be "left", "right" or "both".
- Impossible to invoke a method on a variable (dynamic…
AI-assisted analysis of twigphp/Twig@a414c3a491 (2026-09-13).
Data as JSON: /api/errors/adf8e9ebe6805144.
Report an issue: GitHub.
Appendix: source
Thrown at src/Extension/CoreExtension.php:446
public static function cycle($values, $position): mixed
{
if (!\is_array($values)) {
if (!$values instanceof \ArrayAccess) {
throw new RuntimeError('The "cycle" function expects an array or "ArrayAccess" as first argument.');
}
if (!is_countable($values)) {
// To be uncommented in 4.0
// throw new RuntimeError('The "cycle" function expects a countable sequence as first argument.');
trigger_deprecation('twig/twig', '3.12', 'Passing a non-countable sequence of values to "%s()" is deprecated.', __METHOD__);
$values = self::toArray($values, false);
}
}
if (!$count = \count($values)) {
throw new RuntimeError('The "cycle" function expects a non-empty sequence.');
}
return $values[$position % $count];
}
/**
* Returns a random value depending on the supplied parameter type:
* - a random item from a \Traversable or array
* - a random character from a string
* - a random integer between 0 and the integer parameter.
*
* @param \Traversable|array|int|float|string $values The values to pick a random item from
* @param int|null $max Maximum value used when $values is an int
*
* @return mixed A random value from the given sequence
*
* @throws RuntimeError when $values is an empty array (does not apply to an empty string which is returned as is)
*View on GitHub (pinned to a414c3a491)