sebastianbergmann/phpunit · error · CodeCoverageDriverException

Configured code coverage driver class "%s" is not instantiab

Error message

Configured code coverage driver class "%s" is not instantiable

What it means

The class named in <coverage driver="..."> exists and extends SebastianBergmann\CodeCoverage\Driver\Driver, but ReflectionClass reports it is not instantiable — it is abstract, an interface, an enum, or its constructor is private/protected. PHPUnit reflectively constructs the driver during coverage activation (passing the coverage Filter to the constructor when it has required parameters).

Source

Thrown at src/Runner/CodeCoverage.php:631

            );
        }

        /** @phpstan-ignore classConstant.internalClass */
        if (!is_subclass_of($driverClass, Driver::class)) {
            throw new CodeCoverageDriverException(
                sprintf(
                    'Configured code coverage driver class "%s" does not extend %s',
                    $driverClass,
                    /** @phpstan-ignore classConstant.internalClass */
                    Driver::class,
                ),
            );
        }

        $reflection = new ReflectionClass($driverClass);

        if (!$reflection->isInstantiable()) {
            throw new CodeCoverageDriverException(
                sprintf(
                    'Configured code coverage driver class "%s" is not instantiable',
                    $driverClass,
                ),
            );
        }

        $constructor = $reflection->getConstructor();

        if ($constructor !== null && $constructor->getNumberOfRequiredParameters() > 0) {
            $driver = $reflection->newInstance($filter);
        } else {
            $driver = $reflection->newInstance();
        }

        /** @phpstan-ignore instanceof.internalClass */
        assert($driver instanceof Driver);

View on GitHub (pinned to f123cdb2a2)

Solutions

  1. Point driver at a concrete subclass with a public constructor.
  2. If the constructor is private for singleton reasons, make it public — PHPUnit instantiates the class itself, optionally passing the Filter as the first argument.
  3. For interfaces or abstract families, register the concrete implementation in the attribute instead.

Example fix

<!-- before -->
<coverage driver="App\Coverage\AbstractDriver"/>

<!-- after -->
<coverage driver="App\Coverage\XdebugCliDriver"/>
Defensive patterns

Strategy: validation

Validate before calling

// Preflight: the configured driver must be reflectively instantiable
$class = 'App\\Coverage\\MyDriver';
if (!(new ReflectionClass($class))->isInstantiable()) {
    fwrite(STDERR, "Coverage driver {$class} is abstract or has a non-public constructor\n");
    exit(1);
}

Prevention

When it happens

Trigger: driver pointing at an abstract base class instead of a concrete subclass; an interface extending Driver; a driver whose constructor is private (singleton pattern); an enum-backed driver.

Common situations: Refactoring a driver family and leaving the config pointing at the base; singletons exposing only static getInstance(); a copied driver whose constructor became non-public.

Related errors


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