twigphp/Twig · error · RuntimeError

The "random" function cannot pick from an empty sequence or…

Error message

The "random" function cannot pick from an empty sequence or mapping.

What it means

CoreExtension::random throws this Twig\RuntimeError when the random() function is asked to pick from an empty sequence or mapping: after converting the argument via toArray(), count($values) is 0, so array_rand() would be meaningless and Twig rejects it up front.

Solutions

  1. Guarantee a non-empty collection before calling random(): {{ items|length ? random(items) : fallback }}.
  2. Provide a default: {{ random(items|default(['default-item'])) }}.
  3. If randomness over nothing is acceptable, use the no-argument form random() (picks a random number) instead of random([]).
  4. Fix the data source so the array is populated before rendering.

Example fix

// before (Twig)
<img src="{{ random(banners) }}">

// after
<img src="{{ banners|length ? random(banners) : 'default.png' }}">
Defensive patterns

Strategy: type-guard

Validate before calling

// guard before rendering with random($values)
function pickRandom(array $values, $default = null) {
    return $values !== [] ? $values[array_rand($values)] : $default;
}

Type guard

function isNonEmptyCollection($v): bool { return (is_array($v) || $v instanceof \Traversable) && count($v) > 0; }

Try / catch

try {
    $html = $twig->render('banner.html.twig', ['banners' => $banners]);
} catch (\Twig\Error\RuntimeError $e) {
    if (str_contains($e->getMessage(), '"random" function cannot pick from an empty sequence')) {
        $html = $twig->render('banner.html.twig', ['banners' => ['default.png']]);
    } else { throw $e; }
}

Prevention

When it happens

Trigger: Calling {{ random(emptyArray) }} or twig_random($env, []) — any array/Traversable that toArray()-ed to zero items. (Note: random() with no argument or an integer/overloaded string input follows different branches and does not hit this check.)

Common situations: Picking a random ad/banner from a list that a DB query returned empty; random greeting from a config array not yet populated; null-to-empty coercion feeding random() in a template.

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/b95a958c16458cc6. Report an issue: GitHub.

Appendix: source

Thrown at src/Extension/CoreExtension.php:516

            // unicode version of str_split()
            // split at all positions, but not after the start and not before the end
            $values = preg_split('/(?<!^)(?!$)/u', $values);

            if ('UTF-8' !== $charset) {
                foreach ($values as $i => $value) {
                    $values[$i] = self::convertEncoding($value, $charset, 'UTF-8');
                }
            }
        }

        if (!is_iterable($values)) {
            return $values;
        }

        $values = self::toArray($values);

        if (0 === \count($values)) {
            throw new RuntimeError('The "random" function cannot pick from an empty sequence or mapping.');
        }

        return $values[array_rand($values, 1)];
    }

    /**
     * Formats a date.
     *
     *   {{ post.published_at|date("m/d/Y") }}
     *
     * @param \DateTimeInterface|\DateInterval|string|int|null $date     A date, a timestamp or null to use the current time
     * @param string|null                                      $format   The target format, null to use the default
     * @param \DateTimeZone|string|false|null                  $timezone The target timezone, null to use the default, false to leave unchanged
     */
    public function formatDate($date, $format = null, $timezone = null): string
    {
        if (null === $format) {
            $formats = $this->getDateFormat();

View on GitHub (pinned to a414c3a491)