{"record":{"id":"41f99bfa650411b4","repo":"twigphp/Twig","slug":"calling-the-parent-function-outside-of-a-block-is-forbidden","errorCode":null,"errorMessage":"Calling the \"parent\" function outside of a block is forbidden.","messagePattern":"Calling the \"parent\" function outside of a block is forbidden\\.","errorType":"exception","errorClass":"SyntaxError","httpStatus":null,"severity":"error","filePath":"src/Extension/CoreExtension.php","lineNumber":2224,"sourceCode":"            }\n        } catch (\\Throwable $e) {\n            while (ob_get_level() > $level) {\n                ob_end_clean();\n            }\n\n            throw $e;\n        }\n\n        return ob_get_clean();\n    }\n\n    /**\n     * @internal\n     */\n    public static function parseParentFunction(Parser $parser, Node $fakeNode, $args, int $line): AbstractExpression\n    {\n        if (!$blockName = $parser->peekBlockStack()) {\n            throw new SyntaxError('Calling the \"parent\" function outside of a block is forbidden.', $line, $parser->getStream()->getSourceContext());\n        }\n\n        if (!$parser->hasInheritance()) {\n            throw new SyntaxError('Calling the \"parent\" function on a template that does not call \"extends\" or \"use\" is forbidden.', $line, $parser->getStream()->getSourceContext());\n        }\n\n        return new ParentExpression($blockName, $line);\n    }\n\n    /**\n     * @internal\n     */\n    public static function parseBlockFunction(Parser $parser, Node $fakeNode, $args, int $line): AbstractExpression\n    {\n        $fakeFunction = new TwigFunction('block', static fn ($name, $template = null) => null);\n        $args = (new CallableArgumentsExtractor($fakeNode, $fakeFunction))->extractArguments($args);\n\n        return new BlockReferenceExpression($args[0], $args[1] ?? null, $line);","sourceCodeStart":2206,"sourceCodeEnd":2242,"githubUrl":"https://github.com/twigphp/Twig/blob/a414c3a491defb5a60f2fc88ef79ff37c90010cd/src/Extension/CoreExtension.php#L2206-L2242","documentation":"CoreExtension::parseParentFunction handles the `parent()` call during template compilation. The `parent()` function is only meaningful inside a `{% block %}`; Twig's parser enforces this by peeking at the block stack and throwing a SyntaxError (compile time, not runtime) when the call appears outside any block. Throwing at parse time gives a precise template line and source context.","triggerScenarios":"Writing `{{ parent() }}` (or `{{ parent() }}`-style calls) at template top level, inside a macro, inside a `{% set %}` or `{% filter %}` outside of any block definition — anywhere `$parser->peekBlockStack()` returns null. Note `{% block %}` must still be open: parent() must be lexically inside the block body.","commonSituations":"Copy-pasting `{{ parent() }}` from a child block into a top-level include or macro; moving code out of a block during a refactor and forgetting the parent() call; using parent() inside an embedded template's include rather than its own block override.","solutions":["Move the `{{ parent() }}` call inside a `{% block name %}...{% endblock %}` definition.","If no parent rendering is intended, remove the parent() call entirely.","When reusing block-like markup, use `{% block %}` overrides in a template that extends another, rather than parent() in shared partials.","Re-read the SyntaxError's line/source context to find the misplaced call and relocate it."],"exampleFix":"// before (Twig)\n{{ parent() }}\n{% block content %}...{% endblock %}\n\n// after\n{% block content %}\n  {{ parent() }}\n  ...\n{% endblock %}","handlingStrategy":"validation","validationCode":"// CI lint step (Symfony)\n// php bin/console lint:twig templates/ --format=github\n// fails the build on 'Calling the \"parent\" function outside of a block' before deploy","typeGuard":null,"tryCatchPattern":"try {\n    $twig->parse($twig->tokenize(new \\Twig\\Source($templateCode, $name)));\n} catch (\\Twig\\Error\\SyntaxError $e) {\n    if (str_contains($e->getMessage(), 'outside of a block is forbidden')) {\n        // report template + line for the developer to fix\n    } else { throw $e; }\n}","preventionTips":["Always place {{ parent() }} inside a {% block %} body, never at top level or in macros","Lint all templates in CI (lint:twig) to catch misplacement at build time","When extracting markup out of blocks, search for and relocate any parent() calls","Use {% use %} imports deliberately; remember imported blocks still need their own inheritance context"],"tags":["twig","template-inheritance","syntax-error","compile-time"],"backgroundTag":"invalid-state-transition","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"}