twigphp/Twig · error · SyntaxError
Argument " " could not be assigned for " ( )" because it is…
Error message
Argument "%s" could not be assigned for %s "%s(%s)" because it is mapped to an internal PHP function which cannot determine default value for optional argument%s "%s".
What it means
When a named argument targets an optional parameter of a PHP internal function (extension/built-in), Twig cannot introspect that function's default values via reflection, so it requires that earlier optional parameters be explicitly filled first. If optional arguments were skipped ($missingArguments is non-empty) when trying to assign the named one, compilation fails with this SyntaxError.
Solutions
- Provide all preceding optional arguments positionally before the named one
- Avoid named arguments for functions backed by PHP internals; pass all arguments positionally
- Wrap the internal function in a custom Twig function with explicit parameter defaults
- Check the mapped PHP function's signature and fill gaps
Example fix
// before (template)
{{ substr('hello', start=2) }}
// after
{{ substr('hello', 0, 2) }} Defensive patterns
Strategy: validation
Validate before calling
$ref = new \ReflectionFunction('substr');
foreach ($ref->getParameters() as $p) {
if ($p->isOptional() && $p->getDefaultValue() === null && !$p->isDefaultValueAvailable()) {
// internal function: fill all preceding optional args explicitly
}
} Try / catch
try {
$twig->render($template, $ctx);
} catch (\Twig\Error\SyntaxError $e) {
if (str_contains($e->getMessage(), 'cannot determine default value')) {
// rewrite call to use positional args
}
} Prevention
- Use only positional arguments for filters/functions backed by PHP internals
- Prefer custom Twig wrappers with explicit defaults over mapping raw PHP functions
- Test templates against the target PHP version
When it happens
Trigger: Calling a mapped PHP internal function (e.g. from an extension like twig's core functions using native PHP functions) with a named argument for an optional parameter while skipping a preceding optional parameter, e.g. {{ substr(haystack, offset=1) }} style calls where an earlier optional arg is missing.
Common situations: Named-argument usage on filters/functions backed by native PHP functions (str* functions, etc.); PHP version changes that alter which functions are introspectable; templates ported from userland callables to internal ones.
Understand the failure class
Background: "missing required argument" and "the following required arguments were not provided": what required-argument errors mean and how to fix them — this error's family across 20 libraries.
Related errors
- Named arguments are not supported for
- Argument " " could not be assigned for " ( )" because it is…
- Unknown " " configuration.
- The " " modifier takes exactly one argument (0 given).
- The " " modifier takes exactly one argument (2 given).
AI-assisted analysis of twigphp/Twig@a414c3a491 (2026-09-13).
Data as JSON: /api/errors/6ffbfb02323f94cb.
Report an issue: GitHub.
Appendix: source
Thrown at src/Node/Expression/CallExpression.php:203
foreach ($callableParameters as $callableParameter) {
$name = $this->normalizeName($callableParameter->name);
if (\PHP_VERSION_ID >= 80000 && 'range' === $callable) {
if ('start' === $name) {
$name = 'low';
} elseif ('end' === $name) {
$name = 'high';
}
}
$names[] = $name;
if (\array_key_exists($name, $parameters)) {
if (\array_key_exists($pos, $parameters)) {
throw new SyntaxError(\sprintf('Argument "%s" is defined twice for %s "%s".', $name, $callType, $callName), $this->getTemplateLine(), $this->getSourceContext());
}
if (\count($missingArguments)) {
throw new SyntaxError(\sprintf(
'Argument "%s" could not be assigned for %s "%s(%s)" because it is mapped to an internal PHP function which cannot determine default value for optional argument%s "%s".',
$name, $callType, $callName, implode(', ', $names), \count($missingArguments) > 1 ? 's' : '', implode('", "', $missingArguments)
), $this->getTemplateLine(), $this->getSourceContext());
}
$arguments = array_merge($arguments, $optionalArguments);
$arguments[] = $parameters[$name];
unset($parameters[$name]);
$optionalArguments = [];
} elseif (\array_key_exists($pos, $parameters)) {
$arguments = array_merge($arguments, $optionalArguments);
$arguments[] = $parameters[$pos];
unset($parameters[$pos]);
$optionalArguments = [];
++$pos;
} elseif ($callableParameter->isDefaultValueAvailable()) {
$optionalArguments[] = new ConstantExpression($callableParameter->getDefaultValue(), -1);
} elseif ($callableParameter->isOptional()) {View on GitHub (pinned to a414c3a491)