getgrav/grav · error · UnexpectedValueException
{% script with x %}: x is not an array
Error message
{% script with x %}: x is not an array What it means
The {% script %} tag's compile() emits PHP that assigns the `with <expr>` clause to $attributes and throws UnexpectedValueException unless it is an array (when the clause is absent, $attributes defaults to []). The clause carries script tag attributes, so it must be a Twig mapping or array-valued expression; anything scalar/null aborts the compiled template at render time.
Source
Thrown at system/src/Grav/Common/Twig/Node/TwigNodeScript.php:64
/**
* Compiles the node to PHP.
*
* @param Compiler $compiler A Twig Compiler instance
* @return void
* @throws LogicException
*/
public function compile(Compiler $compiler): void
{
$compiler->addDebugInfo($this);
if ($this->hasNode('attributes')) {
$compiler
->write('$attributes = ')
->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);View on GitHub (pinned to 6040efed04)
Solutions
- Use a mapping literal: {% script 'app.js' in 'bottom' with { defer: true, async: false } %}
- Ensure any variable used is an array: {% set attrs = {defer: true} %} then {% script 'app.js' with attrs %}
- Default null variables: {% set attrs = attrs ?? {} %}
Example fix
{% set defer = true %}
{# before: scalar passed to with #}
{% script 'app.js' in 'bottom' with defer %}
{# after: mapping literal #}
{% script 'app.js' in 'bottom' with { defer: true } %} Defensive patterns
Strategy: validation
Validate before calling
{# in Twig, guard the variable before the tag #}
{% set attrs = attrs is defined and attrs is iterable ? attrs : {} %}
{% script 'app.js' in 'bottom' with attrs %} Try / catch
try { echo $twig->render($template, $data); } catch (UnexpectedValueException $e) { log_template_error($e); } Prevention
- Always write the with clause as a mapping literal: with { defer: true }
- Default attribute variables with ?? {} before the tag
- Review script tags after refactors that move attributes into variables
When it happens
Trigger: {% script 'app.js' in 'bottom' with defer %} where defer is a boolean variable; {% script 'app.js' with 'async' %} (bare string); a `with` variable that is null because the surrounding logic never populated it.
Common situations: Handwritten asset tags missing the attribute braces; attribute variables unset after template refactors; mixing up argument order so a non-array expression lands in the `with` slot.
Related errors
- {% script in x %}: x is not a string
- {% link with x %}: x is not an array
- {% link in x %}: x is not a string
- {% {$this->tagName} with x %}: x is not an array
- {% {$this->tagName} in x %}: x is not a string
AI-assisted analysis of getgrav/grav@6040efed04 (2026-08-17).
Data as JSON: /api/errors/04ad209f1811c646.
Report an issue: GitHub.