twigphp/Twig · error · Twig\Error\RuntimeError

SeparatedTokenList can only be constructed from iterable or…

Error message

SeparatedTokenList can only be constructed from iterable or scalar values.

What it means

SeparatedTokenList represents a list of tokens joined by a separator (e.g. space-separated classes). Its constructor accepts iterable values (spread into a list) or a scalar (wrapped in a single-element list); any other value — null, arrays-as-objects, resources, objects — raises this RuntimeError.

Solutions

  1. Pass an array/Traversable of tokens or a single scalar value.
  2. Coerce null to [] before constructing.
  3. Cast the value to string or array depending on intent before construction.

Example fix

// before
$list = new SeparatedTokenList(' ', $maybeNull);
// after
$list = new SeparatedTokenList(' ', $maybeNull ?? []);
Defensive patterns

Strategy: type-guard

Validate before calling

if (!is_iterable($value) && !is_scalar($value)) {
    throw new InvalidArgumentException('SeparatedTokenList requires iterable or scalar');
}
$list = new SeparatedTokenList(' ', $value);

Type guard

function isValidTokenListValue(mixed $v): bool {
    return is_iterable($v) || is_scalar($v);
}

Try / catch

try {
    $list = new SeparatedTokenList(' ', $value);
} catch (\Twig\Error\RuntimeError $e) {
    if (str_contains($e->getMessage(), 'SeparatedTokenList can only be constructed')) {
        $list = new SeparatedTokenList(' ', []);
    } else {
        throw $e;
    }
}

Prevention

When it happens

Trigger: Calling new SeparatedTokenList(' ', null), new SeparatedTokenList(',', new stdClass()), or passing a non-iterable/non-scalar expression to a class-list attribute helper in a template.

Common situations: A class-list variable is null because a lookup returned nothing, or an object was passed where an array was expected.

Related errors


AI-assisted analysis of twigphp/Twig@a414c3a491 (2026-09-13). Data as JSON: /api/errors/1ef14333cb49e677. Report an issue: GitHub.

Appendix: source

Thrown at extra/html-extra/HtmlAttr/SeparatedTokenList.php:30

namespace Twig\Extra\Html\HtmlAttr;

use Twig\Error\RuntimeError;

/**
 * @author Matthias Pigulla <mp@webfactory.de>
 */
final class SeparatedTokenList implements AttributeValueInterface, MergeableInterface
{
    private readonly array $value;

    public function __construct(mixed $value, private readonly string $separator = ' ')
    {
        if (is_iterable($value)) {
            $this->value = [...$value];
        } elseif (\is_scalar($value)) {
            $this->value = [$value];
        } else {
            throw new RuntimeError('SeparatedTokenList can only be constructed from iterable or scalar values.');
        }
    }

    public function mergeInto(mixed $previous): mixed
    {
        if ($previous instanceof self && $previous->separator === $this->separator) {
            return new self([...$previous->value, ...$this->value], $this->separator);
        }

        if (is_iterable($previous)) {
            return new self([...$previous, ...$this->value], $this->separator);
        }

        throw new RuntimeError('SeparatedTokenList can only be merged with iterables or other SeparatedTokenList instances using the same separator.');
    }

    public function appendFrom(mixed $newValue): mixed
    {

View on GitHub (pinned to a414c3a491)