{"record":{"id":"90d9839f2e0f4220","repo":"python/cpython","slug":"skip-file-prefixes-must-be-a-tuple-of-strs","errorCode":null,"errorMessage":"skip_file_prefixes must be a tuple of strs.","messagePattern":"skip_file_prefixes must be a tuple of strs\\.","errorType":"exception","errorClass":"TypeError","httpStatus":null,"severity":"error","filePath":"Lib/_py_warnings.py","lineNumber":482,"sourceCode":"# 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:\n                    raise ValueError\n    except ValueError:\n        globals = sys.__dict__\n        filename = \"<sys>\"","sourceCodeStart":464,"sourceCodeEnd":500,"githubUrl":"https://github.com/python/cpython/blob/bc6749cc3b5ae4a5e88a6cc2d5b3bebbe354eae6/Lib/_py_warnings.py#L464-L500","documentation":"Raised by warnings.warn (pure-Python fallback path) when skip_file_prefixes is not a tuple. This keyword, used to attribute warnings to the first frame outside given library prefixes, is required to be a tuple because the performance-sensitive C implementation iterates it without type dispatch; lists, sets, or None are rejected with TypeError.","triggerScenarios":"warnings.warn('msg', DeprecationWarning, skip_file_prefixes=[site_packages]) — passing a list; skip_file_prefixes=None; a generator or set passed by generic wrapper code that forwards *args/**kwargs.","commonSituations":"Callers naturally writing a list literal; libraries exposing a variadic warn wrapper that forwards collections verbatim; default mutable-argument style leading to a list default.","solutions":["Pass a tuple: skip_file_prefixes=(str(package_path), ...)","Convert at the boundary: tuple(skip_file_prefixes) in wrappers","Omit the keyword entirely when you don't need frame skipping"],"exampleFix":"# before\nwarnings.warn('deprecated', DeprecationWarning,\n            skip_file_prefixes=[str(pkg_dir)])  # list -> TypeError\n\n# after\nwarnings.warn('deprecated', DeprecationWarning,\n            skip_file_prefixes=(str(pkg_dir),))","handlingStrategy":"type-guard","validationCode":"def warn_external(message, category=Warning, *, prefixes=()):\n    import warnings\n    prefixes = tuple(prefixes) if prefixes is not None else ()\n    return warnings.warn(message, category, skip_file_prefixes=prefixes)","typeGuard":"def is_str_tuple(v) -> bool:\n    return isinstance(v, tuple) and all(isinstance(p, str) for p in v)","tryCatchPattern":null,"preventionTips":["Always use a tuple literal (item,) for skip_file_prefixes","Convert collections at wrapper boundaries with tuple(...)","Remember stacklevel is auto-raised when prefixes are supplied; don't double-adjust"],"tags":["warnings","validation","tuple","stacklevel"],"backgroundTag":null,"analyzedSha":"bc6749cc3b5ae4a5e88a6cc2d5b3bebbe354eae6","analyzedAt":"2026-08-14T22:01:13.976Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}