twigphp/Twig · error · LogicException
Node " " does not exist for Node " ".
Error message
Node "%s" does not exist for Node "%s".
What it means
Node::getNode() throws when the requested child node key is absent from the node's $nodes map. Twig nodes hold their children in named slots (e.g. 'body', 'test', 'left'); asking for a slot this node type never populates indicates the caller assumed the wrong node shape. It is a LogicException for programming errors during compilation or visiting.
Solutions
- Use $node->hasNode('name') before getNode('name'), or iterate with $node->getIterator()/foreach instead of named access.
- Verify the concrete node class and the child slot names it actually defines.
- Branch on instanceof before accessing children so each node type reads its own slots.
- If it appeared after a Twig upgrade, check the CHANGELOG for renamed node children and update the extension.
Example fix
// before
$body = $node->getNode('body');
// after
$body = $node->hasNode('body') ? $node->getNode('body') : null; Defensive patterns
Strategy: type-guard
Validate before calling
if (!$node->hasNode('body')) {
throw new \RuntimeException('Expected "body" child on ' . get_class($node));
} Type guard
$child = $node->hasNode($name) ? $node->getNode($name) : null;
Try / catch
try {
$child = $node->getNode('body');
} catch (\LogicException $e) {
$child = null; // node type has no 'body' child
} Prevention
- Check hasNode() before getNode(), or iterate children generically.
- Use instanceof checks so each node type accesses its own child slots.
- After upgrading Twig, verify node child names used by custom visitors/extensions.
When it happens
Trigger: Calling $node->getNode('body') on a node type without a 'body' child (e.g. on a NameExpression instead of an IfNode); a custom NodeVisitor or optimizer pass that assumes every node has particular children; compiler code shared across node classes with different child layouts.
Common situations: Custom Twig node visitors traversing trees and unconditionally fetching well-known child names; extensions written against an older Twig version where node child names changed; refactored custom nodes where a child was made optional but compiler code still requires it.
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
- Attribute " " does not exist for Node " ".
- 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…
- The tag of a node can only be set once.
AI-assisted analysis of twigphp/Twig@a414c3a491 (2026-09-13).
Data as JSON: /api/errors/311a2a0357ae089b.
Report an issue: GitHub.
Appendix: source
Thrown at src/Node/Node.php:228
{
unset($this->attributes[$name]);
}
/**
* @param string|int $name
*/
public function hasNode(string $name): bool
{
return isset($this->nodes[$name]);
}
/**
* @param string|int $name
*/
public function getNode(string $name): self
{
if (!isset($this->nodes[$name])) {
throw new \LogicException(\sprintf('Node "%s" does not exist for Node "%s".', $name, static::class));
}
$triggerDeprecation = \func_num_args() > 1 ? func_get_arg(1) : true;
if ($triggerDeprecation && isset($this->nodeNameDeprecations[$name])) {
$dep = $this->nodeNameDeprecations[$name];
if ($dep->getNewName()) {
trigger_deprecation($dep->getPackage(), $dep->getVersion(), 'Getting node "%s" on a "%s" class is deprecated, get the "%s" node instead.', $name, static::class, $dep->getNewName());
} else {
trigger_deprecation($dep->getPackage(), $dep->getVersion(), 'Getting node "%s" on a "%s" class is deprecated.', $name, static::class);
}
}
return $this->nodes[$name];
}
/**
* @param string|int $name
*/View on GitHub (pinned to a414c3a491)