diff --git a/reflex/app.py b/reflex/app.py index 6d84e6793d..82a730cd8a 100644 --- a/reflex/app.py +++ b/reflex/app.py @@ -422,14 +422,14 @@ class App(MiddlewareMixin, LifespanMixin): _background_tasks: set[asyncio.Task] = dataclasses.field(default_factory=set) # Frontend Error Handler Function - frontend_exception_handler: Callable[[Exception], None] = ( + frontend_exception_handler: Callable[[Exception], None] | None = ( default_frontend_exception_handler ) # Backend Error Handler Function - backend_exception_handler: Callable[ - [Exception], EventSpec | list[EventSpec] | None - ] = default_backend_exception_handler + backend_exception_handler: ( + Callable[[Exception], EventSpec | list[EventSpec] | None] | None + ) = default_backend_exception_handler # Put the toast provider in the app wrap. toaster: Component | None = dataclasses.field(default_factory=toast.provider) @@ -1620,6 +1620,10 @@ def _validate_exception_handlers(self): ], strict=True, ): + if handler_fn is None: + # If the handler is None, skip validation. + continue + if hasattr(handler_fn, "__name__"): _fn_name = handler_fn.__name__ else: @@ -1665,7 +1669,10 @@ def _validate_exception_handlers(self): raise ValueError(msg) # Check if the return type is valid for backend exception handler - if handler_domain == "backend": + if ( + handler_domain == "backend" + and self.backend_exception_handler is not None + ): sig = inspect.signature(self.backend_exception_handler) return_type = ( eval(sig.return_annotation) @@ -1773,7 +1780,8 @@ async def process( except Exception as ex: telemetry.send_error(ex, context="backend") - app.backend_exception_handler(ex) + if app.backend_exception_handler is not None: + app.backend_exception_handler(ex) raise diff --git a/reflex/state.py b/reflex/state.py index 639fb3dbbe..388620e7a6 100644 --- a/reflex/state.py +++ b/reflex/state.py @@ -1742,8 +1742,11 @@ async def _as_state_update( except Exception as ex: state._clean() + app = prerequisites.get_and_validate_app().app event_specs = ( - prerequisites.get_and_validate_app().app.backend_exception_handler(ex) + app.backend_exception_handler(ex) + if app.backend_exception_handler is not None + else None ) if event_specs is None: @@ -1880,8 +1883,12 @@ async def _process_event( except Exception as ex: telemetry.send_error(ex, context="backend") + app = prerequisites.get_and_validate_app().app + event_specs = ( - prerequisites.get_and_validate_app().app.backend_exception_handler(ex) + app.backend_exception_handler(ex) + if app.backend_exception_handler is not None + else None ) yield await state._as_state_update( @@ -2433,9 +2440,10 @@ def handle_frontend_exception(self, info: str, component_stack: str) -> None: component_stack: The stack trace of the component where the exception occurred. """ - prerequisites.get_and_validate_app().app.frontend_exception_handler( - Exception(info) - ) + app = prerequisites.get_and_validate_app().app + + if app.frontend_exception_handler is not None: + app.frontend_exception_handler(Exception(info)) class UpdateVarsInternalState(State):