{"record":{"id":"5c49bb8b99ee60b1","repo":"python/cpython","slug":"category-must-be-a-warning-subclass-not-class-c","errorCode":null,"errorMessage":"category must be a Warning subclass, not class '{category.__name__}'","messagePattern":"category must be a Warning subclass, not class '(.+?)'","errorType":"exception","errorClass":"TypeError","httpStatus":null,"severity":"error","filePath":"Lib/_py_warnings.py","lineNumber":478,"sourceCode":"        frame = frame.f_back\n    return frame\n\n\n# Code typically replaced by _warnings\ndef warn(message, category=None, stacklevel=1, source=None,\n         *, skip_file_prefixes=()):\n    \"\"\"Issue a warning, or maybe ignore it or raise an exception.\"\"\"\n    # Check if message is already a Warning object\n    if isinstance(message, Warning):\n        category = message.__class__\n    # Check category argument\n    if category is None:\n        category = UserWarning\n    elif not isinstance(category, type):\n        raise TypeError(f\"category must be a Warning subclass, not \"\n                        f\"'{type(category).__name__}'\")\n    elif not issubclass(category, Warning):\n        raise TypeError(f\"category must be a Warning subclass, not \"\n                        f\"class '{category.__name__}'\")\n    if not isinstance(skip_file_prefixes, tuple):\n        # The C version demands a tuple for implementation performance.\n        raise TypeError('skip_file_prefixes must be a tuple of strs.')\n    if skip_file_prefixes:\n        stacklevel = max(2, stacklevel)\n    # Get context information\n    try:\n        if stacklevel <= 1 or _is_internal_frame(sys._getframe(1)):\n            # If frame is too small to care or if the warning originated in\n            # internal code, then do not try to hide any frames.\n            frame = sys._getframe(stacklevel)\n        else:\n            frame = sys._getframe(1)\n            # Look for one frame less since the above line starts us off.\n            for x in range(stacklevel-1):\n                frame = _next_external_frame(frame, skip_file_prefixes)\n                if frame is None:","sourceCodeStart":460,"sourceCodeEnd":496,"githubUrl":"https://github.com/python/cpython/blob/bc6749cc3b5ae4a5e88a6cc2d5b3bebbe354eae6/Lib/_py_warnings.py#L460-L496","documentation":"Raised by the pure-Python warnings.warn fallback when category is a class but does not subclass Warning. warn() instantiates category(message) to build the Warning object, so arbitrary exception classes (ValueError, Exception, custom error hierarchies) are rejected with TypeError naming the offending class.","triggerScenarios":"warnings.warn('bad input', ValueError); warnings.warn('retrying', MyException) where MyException extends Exception; mixing up exception-raising and warning-issuing paths in shared helper code.","commonSituations":"Libraries that 'sometimes warn, sometimes raise' and pass the same exception class to both; new team members assuming warn accepts exceptions; refactoring raises into warns without changing the class; custom exceptions meant to double as warning categories.","solutions":["Define the warning as a Warning subclass: class MyWarning(UserWarning): ... and pass that","Pick a built-in category that fits (UserWarning, DeprecationWarning, RuntimeWarning, FutureWarning, ResourceWarning)","If you actually want an exception, use raise, not warnings.warn"],"exampleFix":"# before\nclass ConfigError(Exception): ...\nwarnings.warn('unknown key', ConfigError)  # TypeError: not a Warning subclass\n\n# after\nclass ConfigWarning(UserWarning): ...\nwarnings.warn('unknown key', ConfigWarning)","handlingStrategy":"type-guard","validationCode":"def as_warning_category(cat):\n    if isinstance(cat, type) and issubclass(cat, Warning):\n        return cat\n    raise TypeError(f'{cat!r} is not a Warning subclass; derive it from Warning/UserWarning')\n\nimport warnings\nwarnings.warn('deprecated', as_warning_category(cfg_category))","typeGuard":"def is_warning_class(cat) -> bool:\n    return isinstance(cat, type) and issubclass(cat, Warning)","tryCatchPattern":null,"preventionTips":["Model 'warnable conditions' as Warning subclasses, separate from exception hierarchies","Common mapping: recoverable deprecation -> DeprecationWarning; runtime concern -> RuntimeWarning","If the condition should abort, raise the exception instead of warning with it"],"tags":["warnings","validation","category","exceptions"],"backgroundTag":null,"analyzedSha":"bc6749cc3b5ae4a5e88a6cc2d5b3bebbe354eae6","analyzedAt":"2026-08-14T22:01:13.976Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}