{"id":"77af1ea60403b000","repo":"pallets/flask","slug":"exc-class-r-is-an-instance-not-a-class-handler","errorCode":null,"errorMessage":"{exc_class!r} is an instance, not a class. Handlers can only be registered for Exception classes or HTTP error codes.","messagePattern":"(.+?) is an instance, not a class\\. Handlers can only be registered for Exception classes or HTTP error codes\\.","errorType":"validation","errorClass":"TypeError","httpStatus":null,"severity":"error","filePath":"src/flask/sansio/scaffold.py","lineNumber":682,"sourceCode":"        :param exc_class_or_code: Any exception class, or an HTTP status\n            code as an integer.\n        \"\"\"\n        exc_class: type[Exception]\n\n        if isinstance(exc_class_or_code, int):\n            try:\n                exc_class = default_exceptions[exc_class_or_code]\n            except KeyError:\n                raise ValueError(\n                    f\"'{exc_class_or_code}' is not a recognized HTTP\"\n                    \" error code. Use a subclass of HTTPException with\"\n                    \" that code instead.\"\n                ) from None\n        else:\n            exc_class = exc_class_or_code\n\n        if isinstance(exc_class, Exception):\n            raise TypeError(\n                f\"{exc_class!r} is an instance, not a class. Handlers\"\n                \" can only be registered for Exception classes or HTTP\"\n                \" error codes.\"\n            )\n\n        if not issubclass(exc_class, Exception):\n            raise ValueError(\n                f\"'{exc_class.__name__}' is not a subclass of Exception.\"\n                \" Handlers can only be registered for Exception classes\"\n                \" or HTTP error codes.\"\n            )\n\n        if issubclass(exc_class, HTTPException):\n            return exc_class, exc_class.code\n        else:\n            return exc_class, None\n\n","sourceCodeStart":664,"sourceCodeEnd":700,"githubUrl":"https://github.com/pallets/flask/blob/6a2f545bfd8ed31e19066a299296917e034aca58/src/flask/sansio/scaffold.py#L664-L700","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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)."],"exampleFix":"# before\n@app.errorhandler(ValueError())\ndef handle(e): ...\n# after\n@app.errorhandler(ValueError)\ndef handle(e): ...","handlingStrategy":"type-guard","validationCode":null,"typeGuard":"import inspect\ndef is_valid_handler_key(key) -> bool:\n    return isinstance(key, int) or (inspect.isclass(key) and issubclass(key, Exception))","tryCatchPattern":null,"preventionTips":["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"],"tags":["flask","error-handling","type-error"],"analyzedSha":"6a2f545bfd8ed31e19066a299296917e034aca58","analyzedAt":"2026-07-31T19:13:49.921Z","schemaVersion":2}