From 760026aaa876c873489261ae6b273abbf3daad7b Mon Sep 17 00:00:00 2001 From: mujiaho <2787173961@qq.com> Date: Thu, 28 May 2026 03:33:55 +0800 Subject: [PATCH] fix: isolate event handler errors per spec 5.2.5 Wrap handler invocations in try/except within run_client_handlers, run_global_handlers, and _run_immediate_handler so that a failing handler does not prevent subsequent handlers from executing. Log handler name, event type, and full traceback via logger.warning with exc_info=True for debugging visibility. Closes #596 --- openfeature/_event_support.py | 33 ++++++++++++++++++++++++++++++--- 1 file changed, 30 insertions(+), 3 deletions(-) diff --git a/openfeature/_event_support.py b/openfeature/_event_support.py index 00557ead..b9015a88 100644 --- a/openfeature/_event_support.py +++ b/openfeature/_event_support.py @@ -1,9 +1,12 @@ from __future__ import annotations +import logging import threading import typing from collections import defaultdict +logger = logging.getLogger(__name__) + from openfeature.event import ( EventDetails, EventHandler, @@ -30,13 +33,29 @@ def run_client_handlers( ) -> None: with _client_lock: for handler in _client_handlers[client][event]: - handler(details) + try: + handler(details) + except Exception: + logger.warning( + "Error in client handler %s for event %s", + getattr(handler, "__name__", repr(handler)), + event, + exc_info=True, + ) def run_global_handlers(event: ProviderEvent, details: EventDetails) -> None: with _global_lock: for handler in _global_handlers[event]: - handler(details) + try: + handler(details) + except Exception: + logger.warning( + "Error in global handler %s for event %s", + getattr(handler, "__name__", repr(handler)), + event, + exc_info=True, + ) def add_client_handler( @@ -98,7 +117,15 @@ def _run_immediate_handler( ProviderStatus.STALE: ProviderEvent.PROVIDER_STALE, } if event == status_to_event.get(client.get_provider_status()): - handler(EventDetails(provider_name=client.provider.get_metadata().name)) + try: + handler(EventDetails(provider_name=client.provider.get_metadata().name)) + except Exception: + logger.warning( + "Error in immediate handler %s for event %s", + getattr(handler, "__name__", repr(handler)), + event, + exc_info=True, + ) def clear() -> None: