pallets/flask · error · TypeError
{exc_class!r} is an instance, not a class. Handlers can only
Error message
{exc_class!r} is an instance, not a class. Handlers can only be registered for Exception classes or HTTP error codes. What it means
Error handlers are registered per exception class, then matched at runtime against raised instances via the class's MRO. Passing an exception instance (e.g. ValueError('bad')) instead of the class would break that lookup, so _get_exc_class_and_code raises TypeError immediately at registration time.
Source
Thrown at src/flask/sansio/scaffold.py:682
:param exc_class_or_code: Any exception class, or an HTTP status
code as an integer.
"""
exc_class: type[Exception]
if isinstance(exc_class_or_code, int):
try:
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
View on GitHub ↗ (pinned to 6a2f545bfd)
Solutions
- Drop the parentheses / pass the class itself: @app.errorhandler(ValueError).
- If you have an instance in hand, register its type: app.register_error_handler(type(e), fn).
Example fix
# before @app.errorhandler(ValueError()) def handle(e): ... # after @app.errorhandler(ValueError) def handle(e): ...
Defensive patterns
Strategy: type-guard
Type guard
import inspect
def is_valid_handler_key(key) -> bool:
return isinstance(key, int) or (inspect.isclass(key) and issubclass(key, Exception)) Prevention
- Register the exception CLASS (register_error_handler(ValueError, h)), never an instance (ValueError('x'))
- Watch for accidental parentheses: MyError vs MyError()
- If keys come from config/plugins, run them through the type guard before registering
When it happens
Trigger: app.register_error_handler(ValueError('oops'), fn) or @app.errorhandler(SomeError()) — i.e. the argument has parentheses, instantiating the exception rather than referencing the class.
Common situations: Accidentally calling the exception class in the decorator; passing a caught exception object (except Exception as e: app.register_error_handler(e, ...)); confusion with APIs that accept instances.
Related errors
- Allowed methods must be a list of strings, for example: @app
- '{exc_class_or_code}' is not a recognized HTTP error code. U
- '{exc_class.__name__}' is not a subclass of Exception. Handl
- Working outside of application context. Attempted to use fu
- Working outside of request context. Attempted to use functi
AI-assisted analysis of pallets/flask@6a2f545bfd (2026-07-31).
Data as JSON: /data/errors/77af1ea60403b000.json.
Report an issue: GitHub ↗.