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

  1. Ensure the sequence passed to cycle has at least one element; provide defaults, e.g. cycle(values|default(['a','b']), i).
  2. Guard the loop: only call cycle when the collection is non-empty (or rely on a for loop that skips empty sets).
  3. If the value may be null, coalesce first: cycle(someArray ?? ['odd','even'], loop.index0).
  4. 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

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


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)