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

  1. Use $node->hasNode('name') before getNode('name'), or iterate with $node->getIterator()/foreach instead of named access.
  2. Verify the concrete node class and the child slot names it actually defines.
  3. Branch on instanceof before accessing children so each node type reads its own slots.
  4. 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

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


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)