twigphp/Twig · error · LogicException
Attribute " " does not exist for Node " ".
Error message
Attribute "%s" does not exist for Node "%s".
What it means
Node::getAttribute() throws when the requested attribute key does not exist on the node's $attributes array. Twig nodes store metadata (names, values, flags) in attributes; requesting a key the node never had means the caller assumes a node shape that differs from the actual node. It is a LogicException signaling a programming error in a compiler, visitor, or extension.
Solutions
- Call $node->hasAttribute('name') before getAttribute(), or use $node->getAttribute('name', false) where deprecation-triggering argument applies.
- Check the actual node class (get_class($node)) and only request attributes that class defines.
- If handling multiple node types, branch on instanceof before accessing attributes.
- If caused by a Twig upgrade, consult the CHANGELOG for renamed node attributes and update custom code.
Example fix
// before
$name = $node->getAttribute('name');
// after
$name = $node->hasAttribute('name') ? $node->getAttribute('name') : null; Defensive patterns
Strategy: type-guard
Validate before calling
if (!$node->hasAttribute('name')) {
throw new \RuntimeException('Unexpected node shape: no "name" attribute on ' . get_class($node));
} Type guard
$attr = $node->hasAttribute($name) ? $node->getAttribute($name) : null;
Try / catch
try {
$value = $node->getAttribute('name');
} catch (\LogicException $e) {
$value = null; // attribute absent for this node type
} Prevention
- Check hasAttribute() before getAttribute().
- Branch on instanceof to only read attributes the concrete node class defines.
- After Twig upgrades, diff node attribute names used by your extensions against the CHANGELOG.
When it happens
Trigger: Calling $node->getAttribute('name') on a node type that has no 'name' attribute, e.g. calling NodeExpression Name methods on a ConstantExpression, or a custom visitor/compiler pass assuming every node carries attributes like 'value', 'raw', or 'always_defined'.
Common situations: Custom Twig extensions or dump-style debug visitors inspecting heterogeneous nodes and assuming a uniform attribute set; upgrading Twig where a node attribute was renamed/removed (attribute deprecations exist in this code) while custom code still requests the old name; copy-pasted compiler code applied to the wrong node class.
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
- Node " " does not exist for Node " ".
- Impossible to access an attribute/key on a variable…
- The "deprecation_info" option must be an instance of
- A block chain cannot contain templates from different Twig…
- Using " " for the value of node " " of " " is not…
AI-assisted analysis of twigphp/Twig@a414c3a491 (2026-09-13).
Data as JSON: /api/errors/07fb32e277c617d0.
Report an issue: GitHub.
Appendix: source
Thrown at src/Node/Node.php:173
*/
public function setNodeTag(string $tag): void
{
if ($this->tag) {
throw new \LogicException('The tag of a node can only be set once.');
}
$this->tag = $tag;
}
public function hasAttribute(string $name): bool
{
return \array_key_exists($name, $this->attributes);
}
public function getAttribute(string $name)
{
if (!\array_key_exists($name, $this->attributes)) {
throw new \LogicException(\sprintf('Attribute "%s" does not exist for Node "%s".', $name, static::class));
}
$triggerDeprecation = \func_num_args() > 1 ? func_get_arg(1) : true;
if ($triggerDeprecation && isset($this->attributeNameDeprecations[$name])) {
$dep = $this->attributeNameDeprecations[$name];
if ($dep->getNewName()) {
trigger_deprecation($dep->getPackage(), $dep->getVersion(), 'Getting attribute "%s" on a "%s" class is deprecated, get the "%s" attribute instead.', $name, static::class, $dep->getNewName());
} else {
trigger_deprecation($dep->getPackage(), $dep->getVersion(), 'Getting attribute "%s" on a "%s" class is deprecated.', $name, static::class);
}
}
return $this->attributes[$name];
}
public function setAttribute(string $name, $value): void
{
$triggerDeprecation = \func_num_args() > 2 ? func_get_arg(2) : true;View on GitHub (pinned to a414c3a491)