sebastianbergmann/phpunit · error · InvalidDataProviderException

The key "%s" has already been defined by provider %s

Error message

The key "%s" has already been defined by provider %s

What it means

PHPUnit merges the data sets of every provider attached to a test method into one keyed result (integer keys are appended and never collide; string keys are registered by name). While iterating a #[DataProvider]/#[DataProviderExternal] method's data, a string key was found that another provider (or an earlier row of the same provider) had already registered. The message names the duplicate key and the provider label that defined it first.

Source

Thrown at src/Metadata/Api/DataProvider.php:224

                    if ($validateArgumentCount && $testMethodNumberOfParameters < count($value)) {
                        $this->triggerWarningForArgumentCount(
                            $testMethod,
                            $this->formatKey($key),
                            $providerLabel,
                            count($value),
                            $testMethodNumberOfParameters,
                        );
                    }

                    if (is_int($key)) {
                        $result[] = new ProvidedData($providerLabel, $value);

                        continue;
                    }

                    if (array_key_exists($key, $result)) {
                        throw new InvalidDataProviderException(
                            sprintf(
                                'The key "%s" has already been defined by provider %s',
                                $key,
                                $result[$key]->label(),
                            ),
                        );
                    }

                    $result[$key] = new ProvidedData($providerLabel, $value);
                }
            } catch (Throwable $e) {
                Event\Facade::emitter()->dataProviderMethodFinished(
                    $testMethodValueObject,
                    ...$methodsCalled,
                );

                throw new InvalidDataProviderException(
                    $e->getMessage(),

View on GitHub (pinned to f123cdb2a2)

Solutions

  1. Rename the duplicate key in whichever provider you control so it is unique across ALL providers attached to that test method (the message names the first definer).
  2. If two providers on one test method intentionally use the same keys, merge them into a single provider.
  3. Or drop the string keys and yield without a key — integer keys are appended and cannot collide.

Example fix

// before: both providers on testX return key 'valid'
#[DataProvider('stringProvider')]
#[DataProvider('numberProvider')]
public function testX(string $s, int $n): void {}

// after: make string keys unique across providers
// stringProvider(): ['validString' => ['a', 1]]
// numberProvider(): ['validNumber' => ['b', 2]]
Defensive patterns

Strategy: validation

Validate before calling

// Meta-test: keys must be unique across all providers attached to one method
$all = [];
foreach ([MyTest::stringProvider(), MyTest::numberProvider()] as $provider) {
    foreach ($provider as $key => $_) {
        if (is_string($key)) {
            self::assertArrayNotHasKey($key, $all, "Duplicate provider key '$key'");
            $all[$key] = true;
        }
    }
}

Type guard

function hasUniqueProviderKeys(iterable ...$providers): bool
{
    $seen = [];

    foreach ($providers as $provider) {
        foreach ($provider as $key => $_) {
            if (is_string($key) && isset($seen[$key])) {
                return false;
            }

            if (is_string($key)) {
                $seen[$key] = true;
            }
        }
    }

    return true;
}

Prevention

When it happens

Trigger: The same string key appears twice in one provider's return value, or two #[DataProvider] attributes on one test method produce overlapping string keys (e.g. both return a 'valid' row). The result array is shared across all providers attached to the method.

Common situations: Copy-pasting a provider onto the same test method; merging providers whose generic keys ('ok', 'valid', 'empty') overlap; combining fixture files without deduplicating keys.

Related errors


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