sebastianbergmann/phpunit · error · NoChildTestSuiteException

The current item is not a TestSuite instance and therefore d

Error message

The current item is not a TestSuite instance and therefore does not have any children.

What it means

Thrown by TestSuiteIterator::getChildren() when the current element is a leaf Test (a TestCase) rather than a composite TestSuite. getChildren() must return an iterator over a nested suite, so calling it on a non-container element raises NoChildTestSuiteException after hasChildren() returns false.

Source

Thrown at src/Framework/TestSuiteIterator.php:75

    public function current(): Test
    {
        assert(isset($this->tests[$this->position]));

        return $this->tests[$this->position];
    }

    public function next(): void
    {
        $this->position++;
    }

    /**
     * @throws NoChildTestSuiteException
     */
    public function getChildren(): self
    {
        if (!$this->hasChildren()) {
            throw new NoChildTestSuiteException(
                'The current item is not a TestSuite instance and therefore does not have any children.',
            );
        }

        $current = $this->current();

        assert($current instanceof TestSuite);

        return new self($current);
    }

    public function hasChildren(): bool
    {
        return $this->valid() && $this->current() instanceof TestSuite;
    }
}

View on GitHub (pinned to f123cdb2a2)

Solutions

  1. Guard the descent: call hasChildren() (or check $current instanceof TestSuite) before getChildren()
  2. Handle the leaf case explicitly in your traversal (process the test, do not recurse)
  3. Use the iterator's standard recursive traversal instead of a hand-written one

Example fix

// before
$children = $iterator->getChildren(); // throws on a TestCase node

// after
if ($iterator->hasChildren()) {
    $children = $iterator->getChildren();
} else {
    $test = $iterator->current(); // leaf TestCase, process it
}
Defensive patterns

Strategy: type-guard

Validate before calling

if ($iterator->hasChildren()) {
    $childIterator = $iterator->getChildren();
}

Type guard

/** @param TestSuiteIterator<TestCase> $iterator */
function currentIsSuite(TestSuiteIterator $iterator): bool
{
    return $iterator->current() instanceof \PHPUnit\Framework\TestSuite;
}

Prevention

When it happens

Trigger: Calling $iterator->getChildren() while positioned on a TestCase; custom reporters/filters that walk the iterator tree and unconditionally descend instead of checking for children first.

Common situations: Custom test listeners or collectors traversing suites with a recursive algorithm that assumes every node is composite; iterating a flat suite whose direct children are all TestCases.

Related errors


AI-assisted analysis of sebastianbergmann/phpunit@f123cdb2a2 (2026-08-23). Data as JSON: /api/errors/12769a8766bac1ee. Report an issue: GitHub.