{"record":{"id":"c6c369d3bdffe5eb","repo":"sebastianbergmann/phpunit","slug":"unknown-event-type-s","errorCode":null,"errorMessage":"Unknown event type \"%s\"","messagePattern":"Unknown event type \"(.+?)\"","errorType":"exception","errorClass":"UnknownEventTypeException","httpStatus":null,"severity":"error","filePath":"src/Event/Dispatcher/DirectDispatcher.php","lineNumber":81,"sourceCode":"        $eventClassName = $this->typeMap->map($subscriber);\n\n        if (!array_key_exists($eventClassName, $this->subscribers)) {\n            $this->subscribers[$eventClassName] = [];\n        }\n\n        $this->subscribers[$eventClassName][] = $subscriber;\n    }\n\n    /**\n     * @throws Throwable\n     * @throws UnknownEventTypeException\n     */\n    public function dispatch(Event $event): void\n    {\n        $eventClassName = $event::class;\n\n        if (!$this->typeMap->isKnownEventType($event)) {\n            throw new UnknownEventTypeException(\n                sprintf(\n                    'Unknown event type \"%s\"',\n                    $eventClassName,\n                ),\n            );\n        }\n\n        foreach ($this->tracers as $tracer) {\n            try {\n                $tracer->trace($event);\n                // @codeCoverageIgnoreStart\n            } catch (Throwable $t) {\n                $this->handleThrowable($t);\n            }\n            // @codeCoverageIgnoreEnd\n        }\n\n        if (!array_key_exists($eventClassName, $this->subscribers)) {","sourceCodeStart":63,"sourceCodeEnd":99,"githubUrl":"https://github.com/sebastianbergmann/phpunit/blob/f123cdb2a2d49f15025794166cfed8bda8627dd2/src/Event/Dispatcher/DirectDispatcher.php#L63-L99","documentation":"DirectDispatcher::dispatch() only delivers events whose concrete class is a value in the dispatcher's TypeMap (isKnownEventType() performs in_array($event::class, $mapping, true)). All built-in event classes are seeded by Facade::registerDefaultTypes(); a custom event class with no registered subscriber-interface mapping is rejected before any tracer or subscriber sees it. The check preserves the invariant that every dispatched event is routable.","triggerScenarios":"Calling $dispatcher->dispatch(new MyCustomEvent(...)) with a class implementing PHPUnit\\Event\\Event that was never registered via TypeMap::addMapping(); constructing DirectDispatcher with 'new TypeMap' (empty map) instead of the Facade's seeded map; emitting an event class whose mapping was dropped during a refactor.","commonSituations":"Adding application-specific events in a custom runner built on PHPUnit's Event component; reusing the Event subsystem outside the phpunit binary and forgetting the default map is not auto-populated there; keeping dispatch code that hardcodes event class names across a PHPUnit upgrade that renamed them.","solutions":["Register the event before dispatching: $typeMap->addMapping(MyEventSubscriber::class, MyEvent::class), then dispatch MyEvent through the DirectDispatcher built with that same TypeMap.","For built-in events, emit through Facade::emitter() (DispatchingEmitter) instead of calling dispatch() yourself, so the seeded TypeMap is used.","Ensure registration and dispatch share one TypeMap instance; a map populated after the dispatcher is constructed still works (it is the same object), but a different map will not."],"exampleFix":"// before\n$dispatcher = new DirectDispatcher(new TypeMap); // empty map\n$dispatcher->dispatch(new OrderPlaced($orderId)); // UnknownEventTypeException\n\n// after\n$typeMap = new TypeMap;\n$typeMap->addMapping(OrderPlacedSubscriber::class, OrderPlaced::class);\n$dispatcher = new DirectDispatcher($typeMap);\n$dispatcher->dispatch(new OrderPlaced($orderId));","handlingStrategy":"validation","validationCode":"// TypeMap exposes a public predicate; use the same instance the dispatcher was built with\nif (!$typeMap->isKnownEventType($event)) {\n    $typeMap->addMapping($event::class . 'Subscriber', $event::class); // or skip dispatching\n}\n$typeMap->dispatcher()->dispatch($event);","typeGuard":null,"tryCatchPattern":"try {\n    $dispatcher->dispatch($event);\n} catch (PHPUnit\\Event\\UnknownEventTypeException $e) {\n    // Event class not mapped: register the mapping or drop the custom event\n}","preventionTips":["Keep a single shared TypeMap for registration and dispatching so the mapping sets stay in sync.","For built-in events, emit through Facade::emitter() instead of calling dispatch() directly.","In custom runners, register every custom event's mapping during bootstrap, before the first dispatch."],"tags":["phpunit","event-dispatcher","custom-events","php"],"backgroundTag":"unknown-event-type","analyzedSha":"f123cdb2a2d49f15025794166cfed8bda8627dd2","analyzedAt":"2026-08-23T01:20:58.058Z","schemaVersion":2},"datasetVersion":"2026-08-23T08:06:27.607Z"}