pallets/flask · error · ValueError

' ' is not a subclass of Exception. Handlers can only be…

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

After confirming the value is a class (not an instance), Flask checks issubclass(exc_class, Exception). A class that is not an Exception subclass (e.g. int, str, a plain object subclass) cannot be used as an error-handler key, so it raises ValueError. Handlers can only target Exception subclasses or HTTP codes.

Solutions

  1. Make the target class inherit from Exception (or a more specific exception type) before registering.
  2. Pass an integer HTTP code or a real Exception subclass instead of an unrelated class.
  3. If you intended to handle a non-exception signal, restructure to raise an exception and handle that.

Example fix

// before
class NotFound: ...
app.register_error_handler(NotFound, handler)

// after
class NotFound(Exception): ...
app.register_error_handler(NotFound, handler)
Defensive patterns

Strategy: type-guard

Validate before calling

def validate_error_target(target):
    if isinstance(target, int):
        return target
    if isinstance(target, type) and issubclass(target, Exception):
        return target
    raise ValueError(f'{target!r} is not an Exception subclass or HTTP code')

Type guard

def is_valid_error_target(target) -> bool:
    return (isinstance(target, int)) or (isinstance(target, type) and issubclass(target, Exception))

Prevention

When it happens

Trigger: @app.errorhandler(int); @app.errorhandler(str); @app.errorhandler(SomeDataclass) where the class does not inherit Exception.

Common situations: Registering handlers against status enums, plain classes, or built-in types by mistake; confusing an error code class with an Exception subclass.

Related errors


AI-assisted analysis of pallets/flask@3596b1ab61 (2026-08-11). Data as JSON: /api/errors/c907ba7c31bf9136. Report an issue: GitHub.

Appendix: 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 3596b1ab61)