twigphp/Twig · error · RuntimeError
Accessing \Twig\Template attributes is forbidden.
Error message
Accessing \Twig\Template attributes is forbidden.
What it means
CoreExtension::getAttribute() forbids accessing attributes or calling methods on a \Twig\Template instance itself. This guards template internals (blocks, sources, env) from being inspected or mutated from inside templates.
Solutions
- Remove the Template instance from the template context; pass plain data instead
- If you loaded a template by accident (env->load(...)), render it or use ->renderBlock() server-side rather than passing the object
- Unwrap the value: pass $template->getSourceContext() or rendered output instead of the object
Example fix
// before (PHP controller)
return $this->render('base.html.twig', ['tpl' => $template]);
// after
return $this->render('base.html.twig', ['content' => $template->render([])]); Defensive patterns
Strategy: type-guard
Validate before calling
foreach ($context as $k => $v) { if ($v instanceof \Twig\Template) { throw new \RuntimeException("Context key '$k' holds a Template object"); } } Type guard
function isTwigTemplate($v): bool { return $v instanceof \Twig\Template; } Try / catch
try { $twig->render($tpl, $ctx); } catch (\Twig\Error\RuntimeError $e) { if (str_contains($e->getMessage(), 'attributes is forbidden')) { /* remove Template from context */ } } Prevention
- Never pass Template instances into template context
- Render templates server-side and pass strings
- Audit custom extensions for returning $this or loaded templates
When it happens
Trigger: A template variable holds a Twig\Template object (or a template is passed as context value) and the template does {{ template.someAttr }} or {{ template.someMethod() }}.
Common situations: Passing a Template object into the context by mistake (e.g. from a custom extension returning $this or a loaded template), or iterating over template instances; experimental/internal code doing reflection-ish access from templates.
Understand the failure class
Background: UnsupportedOperationException and "is not supported" errors: when a library deliberately refuses a call — this error's family across 30 libraries.
- Authentication and authorization failures — expired tokens, bad credentials, and missing scopes.
Related errors
- Block " " on template " " does not exist.
- Block " " should not call parent() in " " as the block does…
- Failed to load Twig template
- Impossible to invoke a method on a variable (dynamic…
- Neither the property "%1$s" nor one of the methods…
AI-assisted analysis of twigphp/Twig@a414c3a491 (2026-09-13).
Data as JSON: /api/errors/1ac72b01dd0d58bb.
Report an issue: GitHub.
Appendix: source
Thrown at src/Extension/CoreExtension.php:1850
}
if ($ignoreStrictCheck || !$env->isStrictVariables()) {
return;
}
if (null === $object) {
$message = \sprintf('Impossible to invoke a method ("%s") on a null variable.', $item);
} elseif (\is_array($object)) {
$message = \sprintf('Impossible to invoke a method ("%s") on a sequence/mapping.', $item);
} else {
$message = \sprintf('Impossible to invoke a method ("%s") on a %s variable ("%s").', $item, get_debug_type($object), $object);
}
throw new RuntimeError($message, $lineno, $source);
}
if ($object instanceof Template) {
throw new RuntimeError('Accessing \Twig\Template attributes is forbidden.', $lineno, $source);
}
// object property
if (Template::METHOD_CALL !== $type) {
if ($sandboxed) {
try {
$env->getExtension(SandboxExtension::class)->getChecker()->checkPropertyAllowed($object, $item, $lineno, $source);
} catch (SecurityNotAllowedPropertyError $propertyNotAllowedError) {
goto methodCheck;
}
}
static $propertyCheckers = [];
if (isset($object->$item)
|| ($propertyCheckers[$object::class][$item] ??= self::getPropertyChecker($object::class, $item))($object, $item)
) {
if ($isDefinedTest) {View on GitHub (pinned to a414c3a491)