twigphp/Twig · error · RuntimeError
Variables passed to the "with" tag must be a mapping.
Error message
Variables passed to the "with" tag must be a mapping.
What it means
The {% with %} tag's compiled code evaluates the passed variables and requires an iterable mapping before converting it via CoreExtension::toArray(). Scalars like strings or integers passed to with are rejected at runtime with this RuntimeError.
Solutions
- Pass a hash: {% with { foo: bar } %}...{% endwith %}
- Guard the value: only enter the with-block when the variable is an array
- Fix upstream data so the variable is a mapping
Example fix
// before
{% with settings_string %}...{% endwith %}
// after
{% with { settings: settings_string } %}...{% endwith %} Defensive patterns
Strategy: type-guard
Validate before calling
if (!is_iterable($vars) && !is_array($vars)) {
throw new InvalidArgumentException('{% with %} requires a mapping');
} Type guard
function isMapping(mixed $v): bool {
return is_array($v) || $v instanceof \Traversable;
} Try / catch
try {
$twig->render($template, $context);
} catch (\Twig\Error\RuntimeError $e) {
if (str_contains($e->getMessage(), 'must be a mapping')) {
// coerce/fix the variable passed to {% with %}
}
throw $e;
} Prevention
- Always pass hashes to {% with %}: { key: value }
- Validate upstream data shapes before render
- Coerce scalars to arrays at the controller layer
When it happens
Trigger: {% with foo %}...{% endwith %} or {% with someString %} where the expression is not an array/object (e.g. a string, number, or boolean).
Common situations: Passing a scalar by mistake instead of a hash; a variable expected to be an array being null/string due to upstream data issues.
Understand the failure class
Background: Type mismatch errors: IllegalArgumentException, TypeError and type guards across 150 open-source libraries — this error's family across 150 libraries.
Related errors
- Attributes using InlineStyle can only be merged with…
- Block chain templates must be strings or
- InlineStyle can only be created from iterable values.
- Only empty strings may be passed as string arguments to…
- Only iterable values can be appended to InlineStyle.
AI-assisted analysis of twigphp/Twig@a414c3a491 (2026-09-13).
Data as JSON: /api/errors/5d4e62d2228cb278.
Report an issue: GitHub.
Appendix: source
Thrown at src/Node/WithNode.php:52
public function compile(Compiler $compiler): void
{
$compiler->addDebugInfo($this);
$parentContextName = $compiler->getVarName();
$compiler->write(\sprintf("\$%s = \$context;\n", $parentContextName));
if ($this->hasNode('variables')) {
$node = $this->getNode('variables');
$varsName = $compiler->getVarName();
$compiler
->write(\sprintf('$%s = ', $varsName))
->subcompile($node)
->raw(";\n")
->write(\sprintf("if (!is_iterable(\$%s)) {\n", $varsName))
->indent()
->write("throw new RuntimeError('Variables passed to the \"with\" tag must be a mapping.', ")
->repr($node->getTemplateLine())
->raw(", \$this->getSourceContext());\n")
->outdent()
->write("}\n")
->write(\sprintf("\$%s = CoreExtension::toArray(\$%s);\n", $varsName, $varsName))
;
if ($this->getAttribute('only')) {
$compiler->write("\$context = [];\n");
}
$compiler->write(\sprintf("\$context = \$%s + \$context + \$this->env->getGlobals();\n", $varsName));
}
$compiler
->subcompile($this->getNode('body'))
->write(\sprintf("\$context = \$%s;\n", $parentContextName))
;View on GitHub (pinned to a414c3a491)