sebastianbergmann/phpunit · error · PHPUnit\Framework\GeneratorNotSupportedException

Passing an argument of type Generator for the %s parameter i

Error message

Passing an argument of type Generator for the %s parameter is not supported

What it means

Assert::assertCount(int $expectedCount, Countable|iterable $haystack) explicitly rejects Generator arguments with GeneratorNotSupportedException. Counting a generator consumes it, and its count is not available without iteration, so PHPUnit fails fast instead of producing a misleading or destructive assertion. The message names the parameter that received the generator ($haystack).

Source

Thrown at src/Framework/Assert.php:992

                TraversableContainsOnly::forClassOrInterface($className),
            ),
            $message,
        );
    }

    /**
     * Asserts the number of elements of an array, Countable or Traversable.
     *
     * @param Countable|iterable<mixed> $haystack
     *
     * @throws Exception
     * @throws ExpectationFailedException
     * @throws GeneratorNotSupportedException
     */
    final public static function assertCount(int $expectedCount, Countable|iterable $haystack, string $message = ''): void
    {
        if ($haystack instanceof Generator) {
            throw GeneratorNotSupportedException::fromParameterName('$haystack');
        }

        self::assertThat(
            $haystack,
            new Count($expectedCount),
            $message,
        );
    }

    /**
     * Asserts the number of elements of an array, Countable or Traversable.
     *
     * @param Countable|iterable<mixed> $haystack
     *
     * @throws Exception
     * @throws ExpectationFailedException
     * @throws GeneratorNotSupportedException
     */

View on GitHub (pinned to f123cdb2a2)

Solutions

  1. Materialize before counting: $this->assertCount(3, iterator_to_array($generator))
  2. Or count via iteration: $this->assertSame(3, iterator_count($generator)) — remember this consumes the generator
  3. Keep the generator in a variable and assert on the array form: $items = iterator_to_array($subject->all()); then assert on $items for further checks
  4. If the code under test can reasonably expose an array or Countable, change its return type so counting is safe

Example fix

// before
$subjects = SubjectRepository::streamAll(); // Generator
$this->assertCount(2, $subjects);
// GeneratorNotSupportedException

// after
$subjects = iterator_to_array(SubjectRepository::streamAll());
$this->assertCount(2, $subjects);
Defensive patterns

Strategy: type-guard

Validate before calling

static function countableValue(mixed $value): array
{
    return $value instanceof \Generator ? iterator_to_array($value) : $value;
}

Type guard

static function isGenerator(mixed $value): bool
{
    return $value instanceof \Generator;
}

Try / catch

use PHPUnit\Framework\GeneratorNotSupportedException;

try {
    $this->assertCount($n, $value);
} catch (GeneratorNotSupportedException $e) {
    // materialize once, then assert on the array
    $this->assertCount($n, iterator_to_array($value));
}

Prevention

When it happens

Trigger: Calling $this->assertCount(3, $generator) where $generator is any \Generator — for example the return value of a generator function invoked once, or iterable/implode-style lazy pipelines fed directly into the assertion.

Common situations: Refactoring production code from returning arrays to yielding generators (lazy loading, large datasets) while tests still count results; passing a collection API that yields; generators consumed twice accidentally — the guard also prevents the silent 'already been iterated' bugs.

Related errors


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