{"record":{"id":"9a536ccc13cd88d0","repo":"astral-sh/ruff","slug":"file-name-should-be-non-null-because-path-is-guara","errorCode":null,"errorMessage":"File name should be non-null because path is guaranteed to be a child of `{prefix_dir}`","messagePattern":"File name should be non-null because path is guaranteed to be a child of `(.+?)`","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"critical","filePath":"crates/ty_site_packages/src/lib.rs","lineNumber":1589,"sourceCode":"    prefix_dir: &SystemPath,\n    suffixes: &(impl IntoIterator<Item = InstallationDir> + Clone),\n    implementation: PythonImplementation,\n    system: &dyn System,\n    settings_diagnostic_path: Option<&SystemPath>,\n    directories: &mut SitePackagesPaths,\n) {\n    let Ok(dir_iter) = system.read_directory(prefix_dir) else {\n        return;\n    };\n\n    for entry_result in dir_iter {\n        let Ok(entry) = entry_result else { continue };\n        if !entry.file_type().is_directory() {\n            continue;\n        }\n        let path = entry.into_path();\n        let name = path.file_name().unwrap_or_else(|| {\n            panic!(\n                \"File name should be non-null because path is guaranteed \\\n                to be a child of `{prefix_dir}`\"\n            )\n        });\n\n        let matches_implementation = match implementation {\n            PythonImplementation::CPython | PythonImplementation::GraalPy => {\n                name.starts_with(\"python3.\")\n            }\n            PythonImplementation::PyPy => name.starts_with(\"pypy3.\"),\n            PythonImplementation::Unknown => {\n                name.starts_with(\"python3.\") || name.starts_with(\"pypy3.\")\n            }\n        };\n\n        if matches_implementation {\n            for suffix in suffixes.clone() {\n                let candidate = path.join(suffix.as_str());","sourceCodeStart":1571,"sourceCodeEnd":1607,"githubUrl":"https://github.com/astral-sh/ruff/blob/26f38c119cac42e4d320ba08f09224fdec74af2c/crates/ty_site_packages/src/lib.rs#L1571-L1607","documentation":"While enumerating site-packages directories, ty reads each subdirectory's file name with `Path::file_name()`. Because the entries come from reading a directory directly under a known `prefix_dir`, the file name is expected to always exist; if it does not, this invariant is broken and the code panics. In practice this can occur with odd paths such as entries whose path ends in `..` or filesystem oddities.","triggerScenarios":"Scanning site-packages where a directory entry's path has no final component (file_name() returns None) — e.g. the read_dir root resolving oddly, symlinked or malformed paths under the prefix directory, so the unwrap_or_else panic fires.","commonSituations":"Nonstandard PYTHONPATH/site-packages layouts, broken symlinks or entries created by package managers leaving odd directory names, running ty against an unusual prefix (e.g. a mount point or root) where an entry path normalizes away its file name.","solutions":["Inspect the site-packages directory for malformed or odd-named entries and remove/repair them.","Recreate the virtual environment to restore a clean site-packages layout.","Point ty's interpreter/python-path setting at a standard virtualenv or conda environment with a conventional layout."],"exampleFix":null,"handlingStrategy":"fallback","validationCode":"# Before pointing ty at a prefix, sanity-check its site-packages layout:\nimport pathlib\nfor d in pathlib.Path(site_packages).iterdir():\n    if d.is_dir() and d.name == '':\n        print('malformed entry:', d)","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Use standard virtualenv/conda layouts for interpreter environments.","Clean out broken symlinks and malformed entries from site-packages.","Recreate environments rather than hand-editing site-packages directories."],"tags":["site-packages","filesystem","panic","environment"],"backgroundTag":"malformed-path-entry","analyzedSha":"26f38c119cac42e4d320ba08f09224fdec74af2c","analyzedAt":"2026-09-05T10:32:37.492Z","contentChangedAt":"2026-09-05T10:32:37.492Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}