python/cpython · error · TypeError

category must be a Warning subclass

Error message

category must be a Warning subclass

What it means

Raised by warnings.filterwarnings when category is not a class deriving from Warning. Filters classify warnings by category class, so filterwarnings requires an actual Warning subclass — passing a non-type (an instance) or an unrelated class (e.g. Exception or ValueError) fails this check. Note this site enforces both conditions in one line; the C-accelerated warn() path reports the same condition with a different message.

Source

Thrown at Lib/_py_warnings.py:271

def filterwarnings(action, message="", category=Warning, module="", lineno=0,
                   append=False):
    """Insert an entry into the list of warnings filters (at the front).

    'action' -- one of "error", "ignore", "always", "all", "default", "module",
                or "once"
    'message' -- a regex that the warning message must match
    'category' -- a class that the warning must be a subclass of
    'module' -- a regex that the module name must match
    'lineno' -- an integer line number, 0 matches all warnings
    'append' -- if true, append to the list of filters
    """
    if action not in {"error", "ignore", "always", "all", "default", "module", "once"}:
        raise ValueError(f"invalid action: {action!r}")
    if not isinstance(message, str):
        raise TypeError("message must be a string")
    if not isinstance(category, type) or not issubclass(category, Warning):
        raise TypeError("category must be a Warning subclass")
    if not isinstance(module, str):
        raise TypeError("module must be a string")
    if not isinstance(lineno, int):
        raise TypeError("lineno must be an int")
    if lineno < 0:
        raise ValueError("lineno must be an int >= 0")

    if message or module:
        import re

    if message:
        message = re.compile(message, re.I)
    else:
        message = None
    if module:
        module = re.compile(module)
    else:
        module = None

View on GitHub (pinned to bc6749cc3b)

Solutions

  1. Pass the class itself and make sure it subclasses Warning: category=DeprecationWarning
  2. Resolve string config to the class first: getattr(warnings, name) or importlib, and verify issubclass(cat, Warning)
  3. If you defined a custom category, inherit from Warning (e.g. class MyDep(Warning))
  4. Fix argument order: filterwarnings(action, message_regex, category_class, module_regex, lineno)

Example fix

# before
warnings.filterwarnings('ignore', category=DeprecationWarning())   # instance -> TypeError
warnings.filterwarnings('ignore', category=RuntimeError)            # not a Warning -> TypeError

# after
warnings.filterwarnings('ignore', category=DeprecationWarning)
Defensive patterns

Strategy: type-guard

Validate before calling

def is_warning_category(cat) -> bool:
    return isinstance(cat, type) and issubclass(cat, Warning)

import warnings
if not is_warning_category(category):
    raise TypeError(f'{category!r} is not a Warning subclass')
warnings.filterwarnings('ignore', category=category)

Type guard

def is_warning_category(cat) -> bool:
    return isinstance(cat, type) and issubclass(cat, Warning)

Prevention

When it happens

Trigger: warnings.filterwarnings('ignore', category=DeprecationWarning()) — passing an instance; category=ValueError or category=Exception (not Warning subclasses); category='DeprecationWarning' (a string); passing the message regex into the category slot by argument mix-up.

Common situations: Instantiating the category out of habit; using non-warning exceptions for control flow through the filter API; config-driven category names resolved via getattr on the wrong module; positional-argument mix-ups between message and category.

Related errors


AI-assisted analysis of python/cpython@bc6749cc3b (2026-08-14). Data as JSON: /api/errors/4b45e8426bfc766e. Report an issue: GitHub.