{"id":"bb147564fbedcd9f","repo":"pytest-dev/pytest","slug":"warning-must-be-str-or-warning-got-msg-r-type","errorCode":null,"errorMessage":"Warning must be str or Warning, got {msg!r} (type {type(msg).__name__})","messagePattern":"Warning must be str or Warning, got (.+?) \\(type (.+?)\\)","errorType":"validation","errorClass":"TypeError","httpStatus":null,"severity":"error","filePath":"src/_pytest/recwarn.py","lineNumber":376,"sourceCode":"            # While this can be considered a bug in CPython, we put guards in\n            # pytest as the error message produced without this check in place\n            # is confusing (#10865).\n            for w in self:\n                if type(w.message) is not UserWarning:\n                    # If the warning was of an incorrect type then `warnings.warn()`\n                    # creates a UserWarning. Any other warning must have been specified\n                    # explicitly.\n                    continue\n                if not w.message.args:\n                    # UserWarning() without arguments must have been specified explicitly.\n                    continue\n                msg = w.message.args[0]\n                if isinstance(msg, str):\n                    continue\n                # It's possible that UserWarning was explicitly specified, and\n                # its first argument was not a string. But that case can't be\n                # distinguished from an invalid type.\n                raise TypeError(\n                    f\"Warning must be str or Warning, got {msg!r} (type {type(msg).__name__})\"\n                )\n","sourceCodeStart":358,"sourceCodeEnd":379,"githubUrl":"https://github.com/pytest-dev/pytest/blob/98b357f69e380da908740a212288d73b2ee06687/src/_pytest/recwarn.py#L358-L379","documentation":"When a recorded warning is a UserWarning whose first argument is not a str, pytest raises TypeError. This guards against calls like warnings.warn(123) that produce warnings CPython cannot filter correctly (see cpython#103577). Warnings must carry a str message or be a proper Warning instance.","triggerScenarios":"Code under test (or a dependency) calls warnings.warn(123), warnings.warn(some_object), or warnings.warn() with a non-str, non-Warning first arg, while inside a pytest.warns/recwarn context. Hits recwarn.py:376 during __exit__ re-emission.","commonSituations":"Third-party library emits an invalid warning; test helper passes a non-str message; a refactor changed a warning message variable to a non-str type.","solutions":["Ensure warnings.warn is called with a str message: warnings.warn('text', Category).","Wrap non-str values in str() at the call site: warnings.warn(str(obj)).","If the bad warning comes from a dependency you cannot change, filter or patch it upstream of the pytest.warns block.","Construct a proper Warning instance with a str arg instead of passing a bare object."],"exampleFix":"// before\nimport warnings\nwarnings.warn(123)\n// after\nimport warnings\nwarnings.warn('123')","handlingStrategy":"validation","validationCode":"# before emitting, coerce non-str messages to str\nmsg = 123\nwarnings.warn(str(msg), UserWarning)","typeGuard":"def is_valid_warning_message(msg) -> TypeGuard[str]:\n    return isinstance(msg, str)","tryCatchPattern":null,"preventionTips":["Always call warnings.warn with a str message (or a Warning instance).","Wrap uncertain values in str() at the warn call site.","Patch or filter dependencies that emit non-str warnings upstream of pytest.warns blocks."],"tags":["pytest","warns","validation","type-check"],"analyzedSha":"98b357f69e380da908740a212288d73b2ee06687","analyzedAt":"2026-08-04T20:26:34.442Z","schemaVersion":2}