sebastianbergmann/phpunit · error · InvalidDataProviderException

The key must be an integer or a string, %s given

Error message

The key must be an integer or a string, %s given

What it means

Thrown while iterating a provider's returned data when a key is neither an integer nor a string (get_debug_type() names the actual type in the message). PHPUnit uses each key as the dataset name in test IDs and output, so arrays keyed by, e.g., floats or objects are rejected.

Source

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

                            'Data Provider method %s::%s() does not return an iterable',
                            $className,
                            $methodName,
                        ),
                    );
                }
            } catch (Throwable $e) {
                Event\Facade::emitter()->dataProviderMethodFinished(
                    $testMethodValueObject,
                    ...$methodsCalled,
                );

                throw InvalidDataProviderException::forException($e, $providerLabel);
            }

            try {
                foreach ($data as $key => $value) {
                    if (!is_int($key) && !is_string($key)) {
                        throw new InvalidDataProviderException(
                            sprintf(
                                'The key must be an integer or a string, %s given',
                                get_debug_type($key),
                            ),
                        );
                    }

                    if ($key === '') {
                        throw new InvalidDataProviderException(
                            'The key must not be an empty string',
                        );
                    }

                    if (!is_array($value)) {
                        throw new InvalidDataProviderException(
                            sprintf(
                                'Data set %s provided by %s is invalid, expected array but got %s',
                                $this->formatKey($key),

View on GitHub (pinned to f123cdb2a2)

Solutions

  1. Ensure every dataset key is an int or a non-empty string; cast keys: [(string) $id => $row]
  2. Rebuild the provider with array_values() or a foreach that assigns sequential integer keys
  3. Inspect the provider output (var_export) to find the offending key of the reported type

Example fix

// before
public static function provideCases(): array
{
    $rows = $repository->all(); // keys are float ids
    return $rows;
}

// after
public static function provideCases(): array
{
    $cases = [];

    foreach ($repository->all() as $id => $row) {
        $cases['row ' . $id] = $row;
    }

    return $cases;
}
Defensive patterns

Strategy: validation

Validate before calling

// Normalize keys before returning from a provider
$cases = [];

foreach ($raw as $key => $value) {
    if (!is_int($key) && !is_string($key)) {
        $key = 'case ' . count($cases);
    }

    $cases[$key] = $value;
}

return $cases;

Prevention

When it happens

Trigger: A provider returning [0.5 => [...]] or [$objectKey => [...]] (object/array keys from array_fill_keys or dynamic maps); generators yielding non-scalar keys.

Common situations: Providers built from array_combine with float/string-cast values; spreads of enums-as-keys; data derived from JSON with unexpected key types.

Related errors


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