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

  1. Call $typeMap->isKnownSubscriberType($subscriber) before map() and handle the false branch (skip, or register the missing mapping).
  2. Add the missing mapping with $typeMap->addMapping(MySubscriberInterface::class, MyEvent::class) before calling map().
  3. 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

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


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