{"record":{"id":"6ba7bb5df7d5d0eb","repo":"sebastianbergmann/phpunit","slug":"return-value-for-s-s-cannot-be-generated-s-p","errorCode":null,"errorMessage":"Return value for %s::%s() cannot be generated%s, please configure a return value for this method","messagePattern":"Return value for (.+?)::(.+?)\\(\\) cannot be generated(.+?), please configure a return value for this method","errorType":"exception","errorClass":"RuntimeException","httpStatus":null,"severity":"error","filePath":"src/Framework/MockObject/Runtime/ReturnValueGenerator.php","lineNumber":153,"sourceCode":"                        return $this->testDoubleForIntersectionOfInterfaces($_types, $className, $methodName);\n                    }\n                }\n            }\n        }\n\n        if ($intersection && $this->onlyInterfaces($types)) {\n            return $this->testDoubleForIntersectionOfInterfaces($types, $className, $methodName);\n        }\n\n        $reason = '';\n\n        if ($union) {\n            $reason = ' because the declared return type is a union';\n        } elseif ($intersection) {\n            $reason = ' because the declared return type is an intersection';\n        }\n\n        throw new RuntimeException(\n            sprintf(\n                'Return value for %s::%s() cannot be generated%s, please configure a return value for this method',\n                $className,\n                $methodName,\n                $reason,\n            ),\n        );\n    }\n\n    /**\n     * @param non-empty-list<string> $types\n     */\n    private function onlyInterfaces(array $types): bool\n    {\n        return array_all($types, static fn (string $type) => interface_exists($type));\n    }\n\n    /**","sourceCodeStart":135,"sourceCodeEnd":171,"githubUrl":"https://github.com/sebastianbergmann/phpunit/blob/f123cdb2a2d49f15025794166cfed8bda8627dd2/src/Framework/MockObject/Runtime/ReturnValueGenerator.php#L135-L171","documentation":"Thrown by ReturnValueGenerator::generate() when a stubbed method has no configured return value and the declared return type cannot be auto-generated: a union type (reason ' because the declared return type is a union') or an intersection type (reason '... is an intersection'). PHPUnit cannot pick a member of a union or fabricate an intersection instance, so it demands an explicit willReturn(...).","triggerScenarios":"createStub(Repo::class) where a method is declared : int|string (or : Foo&Bar) and the test never calls ->method(...)->willReturn(...) before the subject invokes it; native return types like :iterable|Countable growing common in PHP 8+ APIs.","commonSituations":"Upgrading a dependency whose methods changed from concrete types to unions (e.g. string|Stringable); partial stubbing where an untouched method is suddenly called by a code path; using stubs as 'smart defaults' and hitting a newly added union-typed getter.","solutions":["Configure the return explicitly: $stub->method('find')->willReturn('n/a') (pick the union member your subject expects).","Or provide logic: ->willReturnCallback(fn () => new Foo()) for intersection types.","For unions including null, willReturn(null) satisfies nullable unions.","If the method should not be called, add expects($this->never()) to make the intent (and failure) explicit."],"exampleFix":"// before\n$store = $this->createStub(Store::class);\n$subject->load($store); // load() calls read(): string|Stream — unconfigured\n\n// after\n$store = $this->createStub(Store::class);\n$store->method('read')->willReturn('stub-content');\n$subject->load($store);","handlingStrategy":"validation","validationCode":"// refuse to rely on generation for union/intersection returns\n$rm = new ReflectionMethod(Repo::class, 'find');\n$type = $rm->getReturnType();\nif ($type instanceof ReflectionUnionType || $type instanceof ReflectionIntersectionType) {\n    $stub->method('find')->willReturn('default'); // explicit member of the union\n}","typeGuard":"function needsExplicitReturn(ReflectionMethod $m): bool\n{\n    $t = $m->getReturnType();\n\n    return $t instanceof ReflectionUnionType\n        || $t instanceof ReflectionIntersectionType;\n}","tryCatchPattern":"try {\n    $subject->load($stub);\n} catch (PHPUnit\\Framework\\MockObject\\RuntimeException $e) {\n    // message names class::method — add ->method(...)->willReturn(...) and rerun\n}","preventionTips":["Never assume auto-generated returns for PHP 8 union/intersection types; always configure them.","When stubbing an unfamiliar API, scan its methods for union/intersection return types first.","Wrap auto-generation failures in test helpers that then report which method needs a configured value."],"tags":["phpunit","mock-object","union-type","intersection-type","return-value-generation"],"backgroundTag":"missing-stub-return-value","analyzedSha":"f123cdb2a2d49f15025794166cfed8bda8627dd2","analyzedAt":"2026-08-23T01:20:58.058Z","schemaVersion":2},"datasetVersion":"2026-08-23T08:06:27.607Z"}