sebastianbergmann/phpunit · error · InvalidDataProviderException
The key "%s" has already been defined by %s
Error message
The key "%s" has already been defined by %s
What it means
The test method carries multiple #[TestWith] / #[TestWithJson] attributes, and PHPUnit keys those data sets by the optional name: argument so names appear in test output. Two attributes on the same test method declared the same name; the message names the attribute index (TestWith#N) that registered it first.
Source
Thrown at src/Metadata/Api/DataProvider.php:390
{
$result = [];
$testMethodNumberOfParameters = $testMethod->getNumberOfParameters();
$testMethodIsNonVariadic = !$testMethod->isVariadic();
$autoIncrementKey = 0;
foreach ($testWith as $i => $_testWith) {
assert($_testWith instanceof TestWith);
$providerLabel = sprintf('TestWith#%s attribute', $i);
$value = $_testWith->data();
if ($_testWith->hasName()) {
$key = $_testWith->name();
assert($key !== null);
if (array_key_exists($key, $result)) {
throw new InvalidDataProviderException(
sprintf(
'The key "%s" has already been defined by %s',
$key,
$result[$key]->label(),
),
);
}
$formattedKey = $this->formatKey($key);
} else {
$key = null;
$formattedKey = $this->formatKey($autoIncrementKey);
}
if (!is_array($value)) {
throw new InvalidDataProviderException(
sprintf(
'Data set %s provided by %s is invalid, expected array but got %s',View on GitHub (pinned to f123cdb2a2)
Solutions
- Rename one of the duplicated name: values on that test method.
- Or drop name: entirely — unnamed #[TestWith] data sets are auto-numbered and never collide.
Example fix
// before #[TestWith([1], name: 'one')] #[TestWith([2], name: 'one')] // after #[TestWith([1], name: 'one')] #[TestWith([2], name: 'two')]
Defensive patterns
Strategy: validation
Validate before calling
// Scan a test method's TestWith attributes for duplicate names before running
$method = new ReflectionMethod(MyTest::class, 'testX');
$names = [];
foreach ($method->getAttributes(TestWith::class) as $attribute) {
$name = $attribute->newInstance()->name();
if ($name !== null) {
self::assertArrayNotHasKey($name, $names, "Duplicate TestWith name '$name'");
$names[$name] = true;
}
} Prevention
- Give each #[TestWith]/#[TestWithJson] on a method a distinct name:.
- Prefer omitting name: when the data itself is self-explanatory.
- Codemod/review check: flag repeated name: values within one method's attribute list.
When it happens
Trigger: Two #[TestWith([...], name: 'edge-case')] attributes, or a #[TestWith] plus a #[TestWithJson], on the same test method using the same name:.
Common situations: Copy-pasting an attribute and forgetting to update name:; combining named and JSON variants with generic names like 'data' or 'test'.
Related errors
- The key "%s" has already been defined by provider %s
- Subscriber "%s" does not implement any known interface - did
- Unknown event type "%s"
- Subscriber "%s" does not implement a known interface
- Subscriber "%s" does not exist or is not an interface
AI-assisted analysis of sebastianbergmann/phpunit@f123cdb2a2 (2026-08-23).
Data as JSON: /api/errors/498685101a29f6f0.
Report an issue: GitHub.