twigphp/Twig · error · RuntimeError

Template " " cannot be used as a trait.

Error message

Template "%s" cannot be used as a trait.

What it means

In {% extends %}/{% use %}-style trait compilation, ModuleNode emits runtime code that loads the trait template and checks isTraitable(). Templates without a block structure (e.g. plain text or templates whose top-level nodes are not blocks) are not traitable and the compiled code throws this RuntimeError at runtime.

Solutions

  1. Ensure the parent/trait template is composed of {% block %} tags
  2. If you meant to include content, use {% include %} instead of {% extends %}/{% use %}
  3. Verify the template name resolves to the intended file

Example fix

// before
{% use 'partials/_fragment.html' %}
// after
{% use 'traits/_form_blocks.html' %} {# contains only {% block %}s #}
Defensive patterns

Strategy: try-catch

Validate before calling

// Pre-check traitability by ensuring the file defines blocks
$src = file_get_contents($traitPath);
if (!preg_match('/{%\\s*block\\s+\\w+/', $src)) {
    throw new InvalidArgumentException("$traitPath is not a traitable template (no blocks)");
}

Try / catch

try {
    $twig->render($template, $context);
} catch (\Twig\Error\RuntimeError $e) {
    if (str_contains($e->getMessage(), 'cannot be used as a trait')) {
        // point extends/use at a block-only template
    }
    throw $e;
}

Prevention

When it happens

Trigger: {% extends 'plain.html' %} where plain.html contains no {% block %} tags, or {% use 'file' %} pointing at a non-block template.

Common situations: Extending a partial/partial-like include by mistake; pointing 'use' at an HTML fragment instead of a block-only template.

Understand the failure class

Background: 'Could not be found', 'does not exist', 'not found in database': the resource-not-found family when an ID, slug, key, or URI lookup comes back empty — this error's family across 20 libraries.

Related errors


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

Appendix: source

Thrown at src/Node/ModuleNode.php:236

        }

        $countTraits = \count($this->getNode('traits'));
        if ($countTraits) {
            $compiler->write("\$this->ensureTraitsAllowed();\n\n");

            foreach ($this->getNode('traits') as $i => $trait) {
                $node = $trait->getNode('template');

                $compiler
                    ->addDebugInfo($node)
                    ->write(\sprintf('$_trait_%s = $this->load(', $i))
                    ->subcompile($node)
                    ->raw(', ')
                    ->repr($node->getTemplateLine())
                    ->raw(");\n")
                    ->write(\sprintf("if (!\$_trait_%s->unwrap()->isTraitable()) {\n", $i))
                    ->indent()
                    ->write("throw new RuntimeError('Template \"'.")
                    ->subcompile($trait->getNode('template'))
                    ->raw(".'\" cannot be used as a trait.', ")
                    ->repr($node->getTemplateLine())
                    ->raw(", \$this->source);\n")
                    ->outdent()
                    ->write("}\n")
                    ->write(\sprintf("\$_trait_%s_blocks = \$_trait_%s->unwrap()->getBlocks();\n\n", $i, $i))
                ;

                foreach ($trait->getNode('targets') as $key => $value) {
                    $compiler
                        ->write(\sprintf('if (!isset($_trait_%s_blocks[', $i))
                        ->string($key)
                        ->raw("])) {\n")
                        ->indent()
                        ->write("throw new RuntimeError(sprintf('Block \"%s\" is not defined in trait \"%s\".', ")
                        ->string($key)
                        ->raw(', ')

View on GitHub (pinned to a414c3a491)