{"record":{"id":"218feed9da06282d","repo":"getgrav/grav","slug":"link-in-x-x-is-not-a-string","errorCode":null,"errorMessage":"{% link in x %}: x is not a string","messagePattern":"(.+?): x is not a string","errorType":"exception","errorClass":"UnexpectedValueException","httpStatus":null,"severity":"error","filePath":"system/src/Grav/Common/Twig/Node/TwigNodeLink.php","lineNumber":79,"sourceCode":"            $compiler\n                ->write('$attributes += ')\n                ->subcompile($this->getNode('attributes'))\n                ->raw(';' . PHP_EOL)\n                ->write('if (!is_array($attributes)) {' . PHP_EOL)\n                ->indent()\n                ->write(\"throw new UnexpectedValueException('{% {$this->tagName} with x %}: x is not an array');\" . PHP_EOL)\n                ->outdent()\n                ->write('}' . PHP_EOL);\n        }\n\n        if ($this->hasNode('group')) {\n            $compiler\n                ->write('$group = ')\n                ->subcompile($this->getNode('group'))\n                ->raw(';' . PHP_EOL)\n                ->write('if (!is_string($group)) {' . PHP_EOL)\n                ->indent()\n                ->write(\"throw new UnexpectedValueException('{% {$this->tagName} in x %}: x is not a string');\" . PHP_EOL)\n                ->outdent()\n                ->write('}' . PHP_EOL);\n        } else {\n            $compiler->write('$group = \\'head\\';' . PHP_EOL);\n        }\n\n        if ($this->hasNode('priority')) {\n            $compiler\n                ->write('$priority = (int)(')\n                ->subcompile($this->getNode('priority'))\n                ->raw(');' . PHP_EOL);\n        } else {\n            $compiler->write('$priority = 10;' . PHP_EOL);\n        }\n\n        $compiler->write(\"\\$assets = \\\\Grav\\\\Common\\\\Grav::instance()['assets'];\" . PHP_EOL);\n        $compiler->write(\"\\$block = \\$context['block'] ?? null;\" . PHP_EOL);\n","sourceCodeStart":61,"sourceCodeEnd":97,"githubUrl":"https://github.com/getgrav/grav/blob/6040efed04efa69b8209448ed81308e7c24147c2/system/src/Grav/Common/Twig/Node/TwigNodeLink.php#L61-L97","documentation":"The {% link %} tag compiles the `in <expr>` clause (the asset group) into $group = <expr> followed by an is_string($group) check; anything else throws UnexpectedValueException when the compiled template runs. The group names where the link asset is placed (default 'head' when the clause is absent) must be a string.","triggerScenarios":"{% link 'a.css' in 5 %} (integer literal); {% link 'a.css' in groupVar %} where groupVar is an array or null; a computed expression like in ['head', 'bottom']|first that unexpectedly yields null.","commonSituations":"Variables used as group names that were never initialized; refactors turning a scalar group into an array; typos where a mapping is passed instead of a bare string.","solutions":["Pass a plain string: {% link 'a.css' in 'head' %}","Default the variable: {% set group = group ?? 'head' %} before the tag","Cast in the expression if the value may be non-string: in group|default('head')"],"exampleFix":"{% set group = ['bottom'] %}\n{# before: array passed to in #}\n{% link 'app.css' in group %}\n\n{# after: string group name #}\n{% link 'app.css' in 'bottom' %}","handlingStrategy":"validation","validationCode":"{# in Twig, guard the group variable before the tag #}\n{% set group = group is defined and group is string ? group : 'head' %}\n{% link 'app.css' in group %}","typeGuard":null,"tryCatchPattern":"try { echo $twig->render($template, $data); } catch (UnexpectedValueException $e) { log_template_error($e); }","preventionTips":["Use plain string literals for asset groups ('head', 'bottom')","Default group expressions with |default('head')","Keep group names as simple scalars in your data model"],"tags":["twig","assets","template","type-error","tag"],"backgroundTag":"twig-tag-argument-type-mismatch","analyzedSha":"6040efed04efa69b8209448ed81308e7c24147c2","analyzedAt":"2026-08-17T05:07:31.593Z","schemaVersion":2},"datasetVersion":"2026-08-17T09:17:11.063Z"}