sebastianbergmann/phpunit · error · InvalidDataProviderException
Data Provider method %s::%s() is not public
Error message
Data Provider method %s::%s() is not public
What it means
Thrown while resolving a @dataProvider annotation/attribute when the referenced provider method exists but is not public. PHPUnit invokes provider methods statically from the framework, so ReflectionMethod::isPublic() is enforced and non-public providers are rejected with InvalidDataProviderException.
Source
Thrown at src/Metadata/Api/DataProvider.php:129
try {
$method = new ReflectionMethod($_dataProvider->className(), $_dataProvider->methodName());
$className = $_dataProvider->className();
$methodName = $_dataProvider->methodName();
if (Test::isTestMethod($method)) {
Event\Facade::emitter()->testRunnerTriggeredPhpunitWarning(
sprintf(
'Method %s::%s() used by test method %s::%s() is also a test method',
$_dataProvider->className(),
$_dataProvider->methodName(),
$testMethod->getDeclaringClass()->getName(),
$testMethod->getName(),
),
);
}
if (!$method->isPublic()) {
throw new InvalidDataProviderException(
sprintf(
'Data Provider method %s::%s() is not public',
$className,
$methodName,
),
);
}
if (!$method->isStatic()) {
throw new InvalidDataProviderException(
sprintf(
'Data Provider method %s::%s() is not static',
$className,
$methodName,
),
);
}
View on GitHub (pinned to f123cdb2a2)
Solutions
- Change the provider method's visibility to public
- Keep the visibility but move the data generation into a public static provider that delegates
Example fix
// before
#[DataProvider('provideCases')]
public function testX(int $n): void { ... }
protected static function provideCases(): array { ... }
// after
#[DataProvider('provideCases')]
public function testX(int $n): void { ... }
public static function provideCases(): array { ... } Defensive patterns
Strategy: validation
Validate before calling
$method = new ReflectionMethod($testClass, 'provideCases');
if (!$method->isPublic()) {
// make it public before running the suite
} Type guard
function isValidDataProvider(ReflectionMethod $method): bool
{
return $method->isPublic()
&& $method->isStatic()
&& $method->getNumberOfParameters() === 0;
} Prevention
- Standardize provider signatures as 'public static function ...()' with zero parameters
- Add a lint/CI check or PHPStan rule asserting provider visibility
When it happens
Trigger: Declaring the provider as protected or private: '#[DataProvider('provideCases')] private static function provideCases(): ...' and running the test.
Common situations: Refactoring tests and changing provider visibility to reduce the public API of test classes; copy-pasting providers from classes where they were protected utilities.
Related errors
- Trying to double property "%s" of class "%s" with doubleProp
- Data Provider method %s::%s() is not static
- Data Provider method %s::%s() expects an argument
- Comparison method %s::%s() does not exist.
- Return value for %s::%s() cannot be generated: %s
AI-assisted analysis of sebastianbergmann/phpunit@f123cdb2a2 (2026-08-23).
Data as JSON: /api/errors/f302a2bb2d368a91.
Report an issue: GitHub.