{"record":{"id":"c2d3c3281e5fdbbc","repo":"twigphp/Twig","slug":"cannot-use-extend-in-a-macro","errorCode":null,"errorMessage":"Cannot use \"extend\" in a macro.","messagePattern":"Cannot use \"extend\" in a macro\\.","errorType":"exception","errorClass":"SyntaxError","httpStatus":null,"severity":"error","filePath":"src/NodeVisitor/CorrectnessNodeVisitor.php","lineNumber":193,"sourceCode":"    private function checkConfigTag(ConfigNode $node): void\n    {\n        if ('extends' === $node->getNodeTag()) {\n            $this->checkExtendsTag($node);\n        }\n\n        if (!isset($this->rootNodes[$node])) {\n            trigger_deprecation('twig/twig', '3.28', 'Using the \"%s\" tag outside the root of a template is deprecated in %s at line %d.', $node->getNodeTag(), $node->getSourceContext()->getName(), $node->getTemplateLine());\n        }\n    }\n\n    private function checkExtendsTag(ConfigNode $node): void\n    {\n        // \"extends\" inside a \"block\" or a \"macro\" has always been a hard error; keep it\n        if ($this->blockDepth) {\n            throw new SyntaxError('Cannot use \"extend\" in a block.', $node->getTemplateLine(), $node->getSourceContext());\n        }\n        if ($this->macroDepth) {\n            throw new SyntaxError('Cannot use \"extend\" in a macro.', $node->getTemplateLine(), $node->getSourceContext());\n        }\n        if ($this->hasExtends) {\n            throw new SyntaxError('Multiple extends tags are forbidden.', $node->getTemplateLine(), $node->getSourceContext());\n        }\n\n        $this->hasExtends = true;\n    }\n\n    private function checkBlockDefinitionNesting(BlockReferenceNode $node): void\n    {\n        // A \"block\" definition nested under an output-wrapping tag is registered globally\n        // regardless of that tag, so the nesting is misleading. This only matters at the root\n        // of a child template's body: once inside a block, a macro, an output capture, or in\n        // a standalone template, the block is rendered in place and behaves like any other.\n        if (!$this->hasParent || $this->blockDepth || $this->macroDepth || $this->capturingNodeDepth || !$this->tagStack) {\n            return;\n        }\n","sourceCodeStart":175,"sourceCodeEnd":211,"githubUrl":"https://github.com/twigphp/Twig/blob/a414c3a491defb5a60f2fc88ef79ff37c90010cd/src/NodeVisitor/CorrectnessNodeVisitor.php#L175-L211","documentation":"Twig forbids an {% extends %} tag inside a {% macro %}. Macros are self-contained callable fragments compiled as standalone units and cannot change the template's inheritance, so checkExtendsTag throws a SyntaxError when macroDepth is non-zero.","triggerScenarios":"An {% extends %} tag placed inside {% macro name() %} ... {% endmacro %}; detected in checkExtendsTag when $this->macroDepth > 0.","commonSituations":"Wrapping an entire template (extends included) into a macro for reuse; code generation that wraps template chunks in macros; confusion between macros and includes when factoring out shared markup.","solutions":["Move {% extends %} out of the macro to the template's top level","Use {% include %} inside the macro instead of extends if you need to render another template","Extract the macro body into a separate template that itself declares the extends"],"exampleFix":"// before\n{% macro wrap() %}\n  {% extends 'base.html.twig' %}\n{% endmacro %}\n// after\n{% extends 'base.html.twig' %}\n{% import _self as m %}{% block content %}{{ m.wrap() }}{% endblock %}","handlingStrategy":"validation","validationCode":"if (preg_match('/{%-?\\\\s*extends\\\\b/', $macroBody)) { throw new \\InvalidArgumentException('extends not allowed inside macro'); }","typeGuard":null,"tryCatchPattern":"try { $env->render($name); } catch (\\Twig\\Error\\SyntaxError $e) { /* invalid extends placement */ }","preventionTips":["Macros are self-contained: use {% include %} for nesting templates","Keep extends tags at template top level","Review generated templates for macro-wrapped inheritance"],"tags":["twig","macros","template-inheritance","syntax-error"],"backgroundTag":"invalid-template-structure","analyzedSha":"a414c3a491defb5a60f2fc88ef79ff37c90010cd","analyzedAt":"2026-09-13T15:10:46.849Z","contentChangedAt":"2026-09-13T15:10:46.849Z","schemaVersion":2},"datasetVersion":"2026-09-16T04:17:20.429Z"}