getgrav/grav · error · UnexpectedValueException

{% {$this->tagName} in x %}: x is not a string

Error message

{% {$this->tagName} in x %}: x is not a string

What it means

The {% style %} tag compiles the `in <expr>` clause (asset group) into $group = <expr> with an is_string($group) check that throws UnexpectedValueException on non-strings at render time; when the clause is absent the group defaults to 'head'. Only string group names are valid.

Source

Thrown at system/src/Grav/Common/Twig/Node/TwigNodeStyle.php:77

                ->subcompile($this->getNode('attributes'))
                ->raw(';' . PHP_EOL)
                ->write('if (!is_array($attributes)) {' . PHP_EOL)
                ->indent()
                ->write("throw new UnexpectedValueException('{% {$this->tagName} with x %}: x is not an array');" . PHP_EOL)
                ->outdent()
                ->write('}' . PHP_EOL);
        } else {
            $compiler->write('$attributes = [];' . PHP_EOL);
        }

        if ($this->hasNode('group')) {
            $compiler
                ->write('$group = ')
                ->subcompile($this->getNode('group'))
                ->raw(';' . PHP_EOL)
                ->write('if (!is_string($group)) {' . PHP_EOL)
                ->indent()
                ->write("throw new UnexpectedValueException('{% {$this->tagName} in x %}: x is not a string');" . PHP_EOL)
                ->outdent()
                ->write('}' . PHP_EOL);
        } else {
            $compiler->write('$group = \'head\';' . PHP_EOL);
        }

        if ($this->hasNode('priority')) {
            $compiler
                ->write('$priority = (int)(')
                ->subcompile($this->getNode('priority'))
                ->raw(');' . PHP_EOL);
        } else {
            $compiler->write('$priority = 10;' . PHP_EOL);
        }

        $compiler->write("\$assets = \\Grav\\Common\\Grav::instance()['assets'];" . PHP_EOL);
        $compiler->write("\$block = \$context['block'] ?? null;" . PHP_EOL);

View on GitHub (pinned to 6040efed04)

Solutions

  1. Pass a plain string: {% style 'a.css' in 'head' %}
  2. Default the expression: in group|default('head')
  3. Initialize the variable first: {% set group = 'head' %}

Example fix

{% set group = ['foot'] %}
{# before: array passed to in #}
{% style 'a.css' in group %}

{# after: string group name #}
{% style 'a.css' in 'foot' %}
Defensive patterns

Strategy: validation

Validate before calling

{# in Twig, guard the group variable before the tag #}
{% set group = group is defined and group is string ? group : 'head' %}
{% style 'theme.css' in group %}

Try / catch

try { echo $twig->render($template, $data); } catch (UnexpectedValueException $e) { log_template_error($e); }

Prevention

When it happens

Trigger: {% style 'a.css' in {name: 'foot'} %} (mapping); {% style 'a.css' in groupVar %} where groupVar is null or a list; computed expressions yielding non-strings.

Common situations: Uninitialized group variables; refactors changing group scalars to arrays; mistaken shorthand where a mapping is used for the group slot.

Related errors


AI-assisted analysis of getgrav/grav@6040efed04 (2026-08-17). Data as JSON: /api/errors/56ec110cc731397c. Report an issue: GitHub.