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 = NoneView on GitHub (pinned to bc6749cc3b)
Solutions
- Pass the class itself and make sure it subclasses Warning: category=DeprecationWarning
- Resolve string config to the class first: getattr(warnings, name) or importlib, and verify issubclass(cat, Warning)
- If you defined a custom category, inherit from Warning (e.g. class MyDep(Warning))
- 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
- Pass Warning subclasses as classes, never instances or strings
- When categories come from config, resolve names to classes and check issubclass(cat, Warning) at parse time
- Keep the argument order action, message, category, module, lineno straight to avoid slot mix-ups
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
- invalid action: {action!r}
- message must be a string
- module must be a string
- lineno must be an int
- lineno must be an int >= 0
AI-assisted analysis of python/cpython@bc6749cc3b (2026-08-14).
Data as JSON: /api/errors/4b45e8426bfc766e.
Report an issue: GitHub.