python/cpython · error · TypeError
message must be a string
Error message
message must be a string
What it means
Raised by warnings.filterwarnings when its message argument is not a str. The message is a regex pattern that the library compiles itself (re.compile(message, re.I)), so passing an already-compiled pattern, bytes, or None is rejected up front with TypeError('message must be a string').
Source
Thrown at Lib/_py_warnings.py:269
return _wm._formatwarnmsg_impl(msg)
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)View on GitHub (pinned to bc6749cc3b)
Solutions
- Pass the raw pattern string: message=r'deprecated api'
- Unwrap compiled patterns before the call: getattr(message, 'pattern', message)
- If you meant 'match everything', pass the empty string '' (default) rather than None
Example fix
# before
import re
warnings.filterwarnings('ignore', message=re.compile('deprecated')) # TypeError
# after
warnings.filterwarnings('ignore', message=r'deprecated') Defensive patterns
Strategy: validation
Validate before calling
def to_pattern_str(msg):
"""Accept a raw string or a compiled regex, return the pattern string."""
return getattr(msg, 'pattern', msg)
import warnings
warnings.filterwarnings('ignore', message=to_pattern_str(user_msg)) Type guard
def is_pattern_str(msg) -> bool:
return isinstance(msg, str) Prevention
- Pass regex pattern strings; filterwarnings compiles them for you
- Unwrap compiled patterns via getattr(p, 'pattern', p) when values come from mixed sources
- Use '' (default) for 'match any message', not None
When it happens
Trigger: warnings.filterwarnings('ignore', message=re.compile('deprecated')) — passing a compiled regex; message=b'...'; message=None explicitly (the default is '' so None passed positionally also trips it).
Common situations: Developers 'pre-compiling' the regex for performance; mixing up argument order so category/message land in the wrong slots; building filter tuples programmatically where a compiled pattern or None leaks into the message field.
Related errors
- module must be a string
- invalid action: {action!r}
- category must be a Warning subclass
- 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/75c94cf3300b4e63.
Report an issue: GitHub.