pallets/flask · error · ValueError
'{exc_class.__name__}' is not a subclass of Exception. Handl
Error message
'{exc_class.__name__}' is not a subclass of Exception. Handlers can only be registered for Exception classes or HTTP error codes. What it means
Flask validates that a registered handler key is actually an Exception subclass, because runtime matching walks the raised exception's class hierarchy. A non-exception class (or any non-int, non-exception object) can never match a raised exception, so registration fails fast with ValueError.
Source
Thrown at src/flask/sansio/scaffold.py:689
exc_class = default_exceptions[exc_class_or_code]
except KeyError:
raise ValueError(
f"'{exc_class_or_code}' is not a recognized HTTP"
" error code. Use a subclass of HTTPException with"
" that code instead."
) from None
else:
exc_class = exc_class_or_code
if isinstance(exc_class, Exception):
raise TypeError(
f"{exc_class!r} is an instance, not a class. Handlers"
" can only be registered for Exception classes or HTTP"
" error codes."
)
if not issubclass(exc_class, Exception):
raise ValueError(
f"'{exc_class.__name__}' is not a subclass of Exception."
" Handlers can only be registered for Exception classes"
" or HTTP error codes."
)
if issubclass(exc_class, HTTPException):
return exc_class, exc_class.code
else:
return exc_class, None
def _endpoint_from_view_func(view_func: ft.RouteCallable) -> str:
"""Internal helper that returns the default endpoint for a given
function. This always is the function name.
"""
assert view_func is not None, "expected view func if endpoint is not provided."
return view_func.__name__
View on GitHub ↗ (pinned to 6a2f545bfd)
Solutions
- Make the custom error class inherit from Exception (or a subclass like RuntimeError/HTTPException).
- If you meant an HTTP status, pass the integer code (e.g. 404) instead of a class.
- Check imports — ensure you're referencing the exception class, not a similarly named model or constant.
Example fix
# before class PaymentError: ... @app.errorhandler(PaymentError) def handle(e): ... # after class PaymentError(Exception): ... @app.errorhandler(PaymentError) def handle(e): ...
Defensive patterns
Strategy: type-guard
Validate before calling
import inspect
assert inspect.isclass(exc) and issubclass(exc, Exception), f"{exc!r} must subclass Exception" Type guard
import inspect
def is_exception_class(obj) -> bool:
return inspect.isclass(obj) and issubclass(obj, Exception) Prevention
- Derive custom error types from Exception (or HTTPException), never from object or BaseException-only mixins
- Don't pass arbitrary classes (enums, dataclasses, sentinels) as handler keys
- Validate plugin-provided handler keys with the type guard at registration time
When it happens
Trigger: @app.errorhandler(SomeClass) or register_error_handler where SomeClass does not inherit from Exception — e.g. a plain class, a BaseException-only subclass (KeyboardInterrupt-style custom), a string, or an enum member.
Common situations: Custom 'error' classes that forgot to inherit Exception; passing a status-code enum instead of an int; registering a Werkzeug Response class or a sentinel by mistake.
Related errors
- '{exc_class_or_code}' is not a recognized HTTP error code. U
- {exc_class!r} is an instance, not a class. Handlers can only
- Working outside of application context. Attempted to use fu
- Working outside of request context. Attempted to use functi
- The session is unavailable because no secret key was set. S
AI-assisted analysis of pallets/flask@6a2f545bfd (2026-07-31).
Data as JSON: /data/errors/c907ba7c31bf9136.json.
Report an issue: GitHub ↗.