{"record":{"id":"82bbea2097a6b96c","repo":"sebastianbergmann/phpunit","slug":"data-provider-callable-does-not-return-an-iterable","errorCode":null,"errorMessage":"Data Provider callable does not return an iterable","messagePattern":"Data Provider callable does not return an iterable","errorType":"exception","errorClass":"InvalidDataProviderException","httpStatus":null,"severity":"error","filePath":"src/Metadata/Api/DataProvider.php","lineNumber":260,"sourceCode":"                    $e->getMessage(),\n                    $e->getCode(),\n                    $e,\n                );\n            }\n        }\n\n        foreach ($dataProviderClosure as $_dataProvider) {\n            assert($_dataProvider instanceof DataProviderClosureMetadata);\n\n            $providerLabel         = sprintf('callable provided to %s::%s()', $testClassName, $testMethod->getName());\n            $validateArgumentCount = $testMethodIsNonVariadic && $_dataProvider->validateArgumentCount();\n\n            try {\n                $callable = $_dataProvider->closure();\n                $data     = $callable();\n\n                if (!is_iterable($data)) {\n                    throw new InvalidDataProviderException(\n                        'Data Provider callable does not return an iterable',\n                    );\n                }\n            } catch (Throwable $e) {\n                Event\\Facade::emitter()->dataProviderMethodFinished(\n                    $testMethodValueObject,\n                    ...$methodsCalled,\n                );\n\n                throw InvalidDataProviderException::forException($e, $providerLabel);\n            }\n\n            foreach ($data as $key => $value) {\n                if (!is_int($key) && !is_string($key)) {\n                    Event\\Facade::emitter()->dataProviderMethodFinished(\n                        $testMethodValueObject,\n                        ...$methodsCalled,\n                    );","sourceCodeStart":242,"sourceCodeEnd":278,"githubUrl":"https://github.com/sebastianbergmann/phpunit/blob/f123cdb2a2d49f15025794166cfed8bda8627dd2/src/Metadata/Api/DataProvider.php#L242-L278","documentation":"The test method uses a #[DataProviderClosure(fn () => ...)] attribute (a Closure as data provider). PHPUnit invoked the closure and requires its return value to be iterable (array or Traversable), because each entry becomes one data set. The closure returned something else, so the test errors out before any data set runs.","triggerScenarios":"#[DataProviderClosure(fn () => null)] (implicit or explicit null return), fn () => 'rows' (string), or any closure returning a scalar or a non-Traversable object. Arrays and Generators are fine.","commonSituations":"Closures with an early return that implicitly returns null; refactoring a method provider into a closure and dropping the return statement; closures returning a single value instead of a list of argument arrays.","solutions":["Make the closure return an iterable of argument arrays: #[DataProviderClosure(fn () => [[1, 2], [3, 4]])].","If the closure delegates to another function, verify that function's return value is iterable.","Check for early exits that implicitly return null."],"exampleFix":"// before\n#[DataProviderClosure(fn () => null)]\n\n// after\n#[DataProviderClosure(fn () => [[1, 2], [3, 4]])]","handlingStrategy":"type-guard","validationCode":"// Meta-test: the closure must return an iterable before wiring it into #[DataProviderClosure]\n$closure = fn (): array => [[1, 2]];\nself::assertIsIterable($closure());","typeGuard":"function returnsIterableDataProvider(Closure $provider): bool\n{\n    return is_iterable($provider());\n}","tryCatchPattern":null,"preventionTips":["Declare the closure's return type so PHP itself rejects bad returns: fn (): array => ....","Smoke-test the closure in a unit test before attaching it via #[DataProviderClosure].","Watch for early returns that implicitly return null."],"tags":["phpunit","php","data-provider","closure"],"backgroundTag":"data-provider-invalid-return","analyzedSha":"f123cdb2a2d49f15025794166cfed8bda8627dd2","analyzedAt":"2026-08-23T01:20:58.058Z","schemaVersion":2},"datasetVersion":"2026-08-23T08:06:27.607Z"}