twigphp/Twig · error · Twig\Error\SyntaxError

The " " modifier takes exactly one argument (0 given).

Error message

The "%s" modifier takes exactly one argument (0 given).

What it means

This Twig SyntaxError is thrown when a {% cache %} modifier ('ttl' or 'tags') is followed by '(' but no argument expression before the closing ')'. The parser requires exactly one argument per modifier and reports '0 given'.

Solutions

  1. Supply exactly one expression inside the parentheses, e.g. ttl(60) or tags(['a','b']).
  2. If the value is dynamic, pass a variable: ttl(ttlValue).
  3. Remove the parentheses entirely if no argument is intended (not valid — ttl/tags always require an argument).

Example fix

// before
{% cache ttl() %}...{% endcache %}
// after
{% cache ttl(60) %}...{% endcache %}
Defensive patterns

Strategy: validation

Validate before calling

if (preg_match('/\{\%\s*cache\s+(ttl|tags)\s*\(\s*\)/', $template)) {
    throw new InvalidArgumentException('cache ttl/tags modifiers require exactly one argument');
}

Try / catch

try {
    $twig->render($template);
} catch (\Twig\Error\SyntaxError $e) {
    if (str_contains($e->getMessage(), '(0 given)')) {
        // point developer at the empty modifier call
    }
    throw $e;
}

Prevention

When it happens

Trigger: Template like {% cache ttl() %} or {% cache tags() %} — a modifier with empty parentheses and no expression.

Common situations: Copy-pasting tag syntax where the argument was deleted or left as a placeholder, or generating templates programmatically with empty values.

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


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

Appendix: source

Thrown at extra/cache-extra/TokenParser/CacheTokenParser.php:41

{
    public function parse(Token $token): Node
    {
        $stream = $this->parser->getStream();
        $key = $this->parser->parseExpression();

        $ttl = null;
        $tags = null;
        while ($stream->test(Token::NAME_TYPE)) {
            $k = $stream->getCurrent()->getValue();
            if (!\in_array($k, ['ttl', 'tags'], true)) {
                throw new SyntaxError(\sprintf('Unknown "%s" configuration.', $k), $stream->getCurrent()->getLine(), $stream->getSourceContext());
            }

            $stream->next();
            $stream->expect(Token::OPERATOR_TYPE, '(');
            $line = $stream->getCurrent()->getLine();
            if ($stream->test(Token::PUNCTUATION_TYPE, ')')) {
                throw new SyntaxError(\sprintf('The "%s" modifier takes exactly one argument (0 given).', $k), $line, $stream->getSourceContext());
            }
            $arg = $this->parser->parseExpression();
            if ($stream->test(Token::PUNCTUATION_TYPE, ',')) {
                throw new SyntaxError(\sprintf('The "%s" modifier takes exactly one argument (2 given).', $k), $line, $stream->getSourceContext());
            }
            $stream->expect(Token::PUNCTUATION_TYPE, ')');

            if ('ttl' === $k) {
                $ttl = $arg;
            } elseif ('tags' === $k) {
                $tags = $arg;
            }
        }

        $stream->expect(Token::BLOCK_END_TYPE);
        $body = $this->parser->subparse([$this, 'decideCacheEnd'], true);
        $stream->expect(Token::BLOCK_END_TYPE);

View on GitHub (pinned to a414c3a491)