mockery/mockery · error · InvalidArgumentException
Unknown ReflectionType: %s
Error message
Unknown ReflectionType: %s
What it means
Mockery's Reflector class turns a ReflectionType from the mocked class's method signatures into a string so the generated mock can redeclare the signature. It knows ReflectionNamedType, ReflectionUnionType and ReflectionIntersectionType; anything else falls through to 'Unknown ReflectionType: %s' (Reflector.php:264). This error therefore means your PHP engine produces a reflection type object this Mockery version was never built to understand.
Source
Thrown at library/Mockery/Reflector.php:264
);
$intersect = array_intersect(self::TRAVERSABLE_ARRAY, $types);
if (self::TRAVERSABLE_ARRAY === $intersect) {
$types = array_merge(self::ITERABLE, array_diff($types, self::TRAVERSABLE_ARRAY));
}
return implode(
'|',
array_map(
static function (string $type): string {
return strpos($type, '&') === false ? $type : sprintf('(%s)', $type);
},
$types
)
);
}
throw new InvalidArgumentException('Unknown ReflectionType: ' . get_debug_type($type));
}
/**
* Get the string representation of the given type.
*
* @return list<array{typeHint:string,isPrimitive:bool}>
*/
private static function getTypeInformation(ReflectionType $type, ReflectionClass $declaringClass): array
{
// PHP 8 union types and PHP 8.1 intersection types can be recursively processed
if ($type instanceof ReflectionUnionType || $type instanceof ReflectionIntersectionType) {
$types = [];
foreach ($type->getTypes() as $innerType) {
foreach (self::getTypeInformation($innerType, $declaringClass) as $info) {
if ('null' === $info['typeHint'] && $info['isPrimitive']) {
continue;
}View on GitHub (pinned to c6401d35bc)
Solutions
- Update Mockery: composer update mockery/mockery — each PHP release is supported in a patch/minor release soon after.
- If you cannot update Mockery, pin PHP to a version your Mockery release supports (composer.json require php constraint).
- As a stopgap, mock an interface whose signatures avoid the new type syntax, or configure Mockery's internal-class parameter overrides if the offending signature is on an internal class.
- Report/patch the new ReflectionType subtype upstream — the fallthrough at Reflector.php:264 is exactly where support gets added.
Example fix
// before: PHP 8.1 intersection type + old mockery => Unknown ReflectionType $mock = Mockery::mock(Repo::class); // Repo::find(): A&B // after: upgrade the library that needs the newer PHP types // composer update mockery/mockery $mock = Mockery::mock(Repo::class);
Defensive patterns
Strategy: try-catch
Validate before calling
// Fail fast with an actionable message when the toolchain is too new for this Mockery
if (version_compare(PHP_VERSION, '8.1', '>=') && \Composer\InstalledVersions::getPrettyVersion('mockery/mockery') !== null
&& version_compare(\Composer\InstalledVersions::getPrettyVersion('mockery/mockery'), '1.5', '<')) {
throw new RuntimeException('PHP ' . PHP_VERSION . ' types need mockery >= 1.5; run composer update mockery/mockery');
}
$mock = Mockery::mock(Repo::class); Try / catch
try {
$mock = Mockery::mock(Repo::class);
} catch (\InvalidArgumentException $e) {
if (str_starts_with($e->getMessage(), 'Unknown ReflectionType:')) {
throw new RuntimeException(
'Mockery ' . \Mockery::VERSION . ' does not support a PHP ' . PHP_VERSION . ' type; update mockery/mockery',
0,
$e
);
}
throw $e;
} Prevention
- Upgrade mockery/mockery in lockstep with PHP version upgrades in CI.
- Pin the php platform version in composer.json so old mocks cannot install on new PHP.
- When a new PHP minor ships, check Mockery's changelog before adopting new type syntax in mocked signatures.
When it happens
Trigger: Mocking any class/interface whose method signatures use a type construct introduced after your Mockery release — historically: PHP 8.0 union types on old Mockery, PHP 8.1 intersection types on Mockery < ~1.4.4/1.5, and by construction any future ReflectionType subtype (e.g. from a new PHP minor) on current Mockery. Fires during mock generation/shouldReceive, before any expectation runs.
Common situations: CI image or local PHP upgraded (8.0 → 8.1 → 8.x) while composer.lock kept an old mockery; a dependency introduced intersection-typed signatures; running a cutting-edge PHP RC with a released Mockery version.
Related errors
- Class:%s does not exist
- Class:%s is an abstract class
- %s() cannot be mocked as it is a private method
- No expectations have been added to this composite expectatio
- Matcher class must implement %s, '%s' given.
AI-assisted analysis of mockery/mockery@c6401d35bc (2026-08-21).
Data as JSON: /api/errors/3e3b37102ce69c6a.
Report an issue: GitHub.