sebastianbergmann/phpunit · error · MapError
Subscriber "%s" does not implement a known interface
Error message
Subscriber "%s" does not implement a known interface
What it means
TypeMap::map(Subscriber) resolves which event class a subscriber should be attached to by walking class_implements($subscriber) and returning the first interface present in the mapping array. MapError is thrown when no implemented interface is mapped. DirectDispatcher::registerSubscriber() calls isKnownSubscriberType() first, so that path normally raises UnknownSubscriberTypeException instead; MapError surfaces when map() is invoked directly without that guard.
Source
Thrown at src/Event/TypeMap.php:81
public function isKnownEventType(Event $event): bool
{
return in_array($event::class, $this->mapping, true);
}
/**
* @throws MapError
*
* @return class-string
*/
public function map(Subscriber $subscriber): string
{
foreach (class_implements($subscriber) as $interface) {
if (array_key_exists($interface, $this->mapping)) {
return $this->mapping[$interface];
}
}
throw new MapError(
sprintf(
'Subscriber "%s" does not implement a known interface',
$subscriber::class,
),
);
}
/**
* @param class-string $subscriberInterface
*
* @throws UnknownSubscriberException
*/
private function ensureSubscriberInterfaceExists(string $subscriberInterface): void
{
if (!interface_exists($subscriberInterface)) {
throw new UnknownSubscriberException(
sprintf(
'Subscriber "%s" does not exist or is not an interface',View on GitHub (pinned to f123cdb2a2)
Solutions
- Call $typeMap->isKnownSubscriberType($subscriber) before map() and handle the false branch (skip, or register the missing mapping).
- Add the missing mapping with $typeMap->addMapping(MySubscriberInterface::class, MyEvent::class) before calling map().
- Prefer the built-in subscriber interfaces, which the Facade's default TypeMap already contains.
Example fix
// before
$eventClass = $typeMap->map($subscriber); // MapError when nothing is mapped
// after
if (!$typeMap->isKnownSubscriberType($subscriber)) {
$typeMap->addMapping(MySubscriberInterface::class, MyEvent::class);
}
$eventClass = $typeMap->map($subscriber); Defensive patterns
Strategy: validation
Validate before calling
if (!$typeMap->isKnownSubscriberType($subscriber)) {
$typeMap->addMapping(MySubscriberInterface::class, MyEvent::class);
}
$eventClass = $typeMap->map($subscriber); // safe now Try / catch
try {
$eventClass = $typeMap->map($subscriber);
} catch (PHPUnit\Event\MapError $e) {
// No mapping for any implemented interface: register one or skip this subscriber
} Prevention
- Treat isKnownSubscriberType() as the mandatory precondition of map().
- Keep custom mappings in one bootstrap location so a TypeMap is never used half-configured.
- Prefer built-in subscriber interfaces; the Facade's default map already contains them.
When it happens
Trigger: Calling $typeMap->map($subscriber) on a TypeMap containing no mapping for any interface the subscriber implements; registering a subscriber against a freshly constructed empty TypeMap; calling map() for a custom subscriber interface whose addMapping() was skipped or failed.
Common situations: Building custom dispatchers or runners on top of PHPUnit's Event component; unit tests exercising the Event subsystem directly; refactors that move subscribers between namespaces so their interfaces no longer match the registered keys.
Related errors
- Subscriber "%s" does not extend Subscriber interface
- Event "%s" already assigned
- Subscriber "%s" does not implement any known interface - did
- Subscriber "%s" does not exist or is not an interface
- Event class "%s" does not exist
AI-assisted analysis of sebastianbergmann/phpunit@f123cdb2a2 (2026-08-23).
Data as JSON: /api/errors/eb84a92feddd9919.
Report an issue: GitHub.