phar-io/manifest · error · ElementCollectionException

\DOMElement expected, got \

Error message

\DOMElement expected, got \%s

What it means

ElementCollection::importNodes() walks a DOMNodeList and throws ElementCollectionException if any node is not a DOMElement, using message '\DOMElement expected, got \%s' with the node's actual class (e.g. DOMText, DOMComment). Collections of manifest elements must contain only element nodes.

Solutions

  1. Use an XPath query returning only elements (e.g. //author instead of //author/node())
  2. Strip comments/whitespace text nodes from the DOMNodeList before constructing the collection
  3. Filter with $node instanceof DOMElement when iterating manually

Example fix

// before
new AuthorElementsCollection($xpath->query('//author/node()'));
// after
new AuthorElementsCollection($xpath->query('//author'));
Defensive patterns

Strategy: type-guard

Validate before calling

// filter non-element nodes before constructing the collection
$elements = array_filter(iterator_to_array($nodeList),
    fn($n) => $n instanceof DOMElement);

Type guard

function allElements(DOMNodeList $list): bool {
    foreach ($list as $n) { if (!$n instanceof DOMElement) return false; }
    return true;
}

Try / catch

try {
    $collection = new ExtElementsCollection($nodeList);
} catch (ElementCollectionException $e) {
    // rebuild the list filtering to DOMElement nodes only
}

Prevention

When it happens

Trigger: Building an ElementCollection (or a subclass such as AuthorElements or ExtElements) from an XPath/node list that picked up text nodes or comments between elements.

Common situations: XPath expressions without normalizing whitespace; XML with pretty-printing comments inside list containers; hand-building node lists in tests.

Understand the failure class

Background: Type mismatch errors: IllegalArgumentException, TypeError and type guards across 150 open-source libraries — this error's family across 150 libraries.

Related errors


AI-assisted analysis of phar-io/manifest@c581d4941e (2026-09-14). Data as JSON: /api/errors/9e3d38e0f1896e31. Report an issue: GitHub.

Appendix: source

Thrown at src/xml/ElementCollection.php:60

        return $this->position;
    }

    public function valid(): bool {
        return $this->position < count($this->nodes);
    }

    public function rewind(): void {
        $this->position = 0;
    }

    protected function getCurrentElement(): DOMElement {
        return $this->nodes[$this->position];
    }

    private function importNodes(DOMNodeList $nodeList): void {
        foreach ($nodeList as $node) {
            if (!$node instanceof DOMElement) {
                throw new ElementCollectionException(
                    sprintf('\DOMElement expected, got \%s', get_class($node))
                );
            }

            $this->nodes[] = $node;
        }
    }
}

View on GitHub (pinned to c581d4941e)