{"record":{"id":"0451ec3860fcf791","repo":"Textualize/textual","slug":"no-handler-for-event-name-r","errorCode":null,"errorMessage":"No handler for {event_name!r}","messagePattern":"No handler for (.+?)","errorType":"exception","errorClass":"NoHandler","httpStatus":null,"severity":"warning","filePath":"src/textual/_event_broker.py","lineNumber":37,"sourceCode":"\n    Args:\n        event_name: Event to check from.\n        meta: Meta information (stored in Rich Style)\n\n    Raises:\n        NoHandler: If no handler is found.\n\n    Returns:\n        Action information.\n    \"\"\"\n    event_path = event_name.split(\".\")\n    for key, value in meta.items():\n        if key.startswith(\"@\"):\n            name_args = key[1:].split(\".\")\n            if name_args[: len(event_path)] == event_path:\n                modifiers = name_args[len(event_path) :]\n                return HandlerArguments(set(modifiers), value)\n    raise NoHandler(f\"No handler for {event_name!r}\")\n","sourceCodeStart":19,"sourceCodeEnd":38,"githubUrl":"https://github.com/Textualize/textual/blob/06dbeef4bb70fb718236aa418ed658ef4667a126/src/textual/_event_broker.py#L19-L38","documentation":"extract_handler_actions inspects a method's metadata (keys starting with '@' registered by the @on decorator) to find a handler matching an event path like ('Notification', 'Show'). If no metadata entry matches the event being brokered, it raises NoHandler. Internally this is often caught by _broker_event to skip the method, but when called directly it signals the method has no @on decorator for that event.","triggerScenarios":"Calling extract_handler_actions(method, event_path) on a plain method or a method decorated with @on for a different event; e.g. extracting handlers for ('Notification','Show') from a method decorated @on(Button.Pressed).","commonSituations":"Direct use of the private _event_broker API in tests or custom dispatch loops; decorators missing or applied to the wrong event after refactoring; stale metadata after editing @on arguments.","solutions":["Decorate the target method with @on matching the event class, e.g. @on(NotificationShow)","Verify the event_path passed matches the decorated event, including any modifiers after the '.'","Use widget.post_message/standard dispatch instead of calling extract_handler_actions directly","Catch NoHandler when iterating candidate methods, mirroring _broker_event"],"exampleFix":"# before\ndef handle(self, event) -> None: ...\nextract_handler_actions(handle, ('Notification', 'Show'))  # NoHandler\n\n# after\nfrom textual import on\n\n@on(NotificationShow)\ndef handle(self, event) -> None: ...\nextract_handler_actions(handle, ('Notification', 'Show'))","handlingStrategy":"try-catch","validationCode":"from textual import on\n\ndef has_handler_for(method, event_cls) -> bool:\n    for meta_key in getattr(method, '__textual_on', {}) or {}:\n        if meta_key.lstrip('@').split('.')[:1] == [event_cls.__name__]:\n            return True\n    return False","typeGuard":null,"tryCatchPattern":"from textual._event_broker import NoHandler\ntry:\n    args = extract_handler_actions(method, event_path)\nexcept NoHandler:\n    args = None  # skip this method, not a handler for the event","preventionTips":["Always decorate handlers with @on(EventClass) before extraction","Prefer widget.post_message and Textual's built-in dispatch over the private broker API","Keep the event_path aligned with the @on decorated event name"],"tags":["python","textual","event-handling","decorator","internal-api"],"backgroundTag":"missing-event-handler","analyzedSha":"06dbeef4bb70fb718236aa418ed658ef4667a126","analyzedAt":"2026-08-27T02:36:57.214Z","schemaVersion":2},"datasetVersion":"2026-08-27T03:17:27.898Z"}