twigphp/Twig · error · LogicException

Named arguments are not supported for

Error message

Named arguments are not supported for %s "%s". / Arbitrary positional arguments are not supported for %s "%s".

What it means

Twig throws this LogicException when a callable (filter, function, test) is invoked with named or arbitrary positional (spread) arguments, but the underlying PHP callable's signature does not declare support for them. Twig inspects the callable's reflection to decide which argument-passing styles are allowed, and rejects calls that cannot be mapped onto real parameters.

Solutions

  1. Declare proper named/typed parameters on the PHP callable, e.g. `function my_filter($value, string $foo = '')` so named arguments can be mapped.
  2. Change the template call to positional arguments matching the callable's parameter order.
  3. If the callable should accept arbitrary arguments, add a variadic parameter (`...$args`) and mark the Twig callable as variadic (is_variadic option).

Example fix

// before
$twig->addFunction(new \Twig\TwigFunction('sum', function (...$args) { /* variadic unsupported */ }));
// after
$twig->addFunction(new \Twig\TwigFunction('sum', function (...$args) { return array_sum($args); }, ['is_variadic' => true]));
Defensive patterns

Strategy: validation

Validate before calling

// Before rendering, ensure named args map to real parameters:
$r = new ReflectionFunction('my_filter');
foreach ($namedArgs as $name => $v) {
    if (!$r->getParameters() || !in_array($name, array_map(fn($p) => $p->getName(), $r->getParameters()), true)) {
        throw new InvalidArgumentException("Unknown named argument: $name");
    }
}

Type guard

function supportsNamedArgs(callable $c): bool {
    $r = is_array($c) ? new ReflectionMethod($c[0], $c[1]) : new ReflectionFunction($c);
    foreach ($r->getParameters() as $p) { if (!$p->isVariadic() && $p->isOptional()) return true; }
    return false;
}

Prevention

When it happens

Trigger: Calling a Twig filter/function/test with named arguments (e.g. `my_filter(foo: 1)`) when the PHP function has no matching named parameter, or using argument spreading (e.g. `f(...arr)`), from getArguments() while compiling CallExpression.

Common situations: Upgrading Twig templates that previously relied on positional-only behavior; exposing a custom filter/function whose PHP signature lacks named/variadic parameters; typos in named argument names that Twig cannot bind.

Understand the failure class

Background: "must be a positive integer", "cannot be empty", "invalid argument": how invalid-argument errors work across open-source libraries — this error's family across 33 libraries.

Related errors


AI-assisted analysis of twigphp/Twig@a414c3a491 (2026-09-13). Data as JSON: /api/errors/c899e041684a7885. Report an issue: GitHub.

Appendix: source

Thrown at src/Node/Expression/CallExpression.php:176

                throw new SyntaxError(\sprintf('Positional arguments cannot be used after named arguments for %s "%s".', $callType, $callName), $this->getTemplateLine(), $this->getSourceContext());
            }

            $parameters[$name] = $node;
        }

        $isVariadic = $this->getAttribute('twig_callable')->isVariadic();
        if (!$named && !$isVariadic) {
            return $parameters;
        }

        if (!$callable) {
            if ($named) {
                $message = \sprintf('Named arguments are not supported for %s "%s".', $callType, $callName);
            } else {
                $message = \sprintf('Arbitrary positional arguments are not supported for %s "%s".', $callType, $callName);
            }

            throw new \LogicException($message);
        }

        [$callableParameters, $isPhpVariadic] = $this->getCallableParameters($callable, $isVariadic);
        $arguments = [];
        $names = [];
        $missingArguments = [];
        $optionalArguments = [];
        $pos = 0;
        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';
                }
            }

View on GitHub (pinned to a414c3a491)