astral-sh/ruff · critical
File name should be non-null because path is guaranteed to b
Error message
File name should be non-null because path is guaranteed to be a child of `{prefix_dir}` What it means
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.
Source
Thrown at crates/ty_site_packages/src/lib.rs:1589
prefix_dir: &SystemPath,
suffixes: &(impl IntoIterator<Item = InstallationDir> + Clone),
implementation: PythonImplementation,
system: &dyn System,
settings_diagnostic_path: Option<&SystemPath>,
directories: &mut SitePackagesPaths,
) {
let Ok(dir_iter) = system.read_directory(prefix_dir) else {
return;
};
for entry_result in dir_iter {
let Ok(entry) = entry_result else { continue };
if !entry.file_type().is_directory() {
continue;
}
let path = entry.into_path();
let name = path.file_name().unwrap_or_else(|| {
panic!(
"File name should be non-null because path is guaranteed \
to be a child of `{prefix_dir}`"
)
});
let matches_implementation = match implementation {
PythonImplementation::CPython | PythonImplementation::GraalPy => {
name.starts_with("python3.")
}
PythonImplementation::PyPy => name.starts_with("pypy3."),
PythonImplementation::Unknown => {
name.starts_with("python3.") || name.starts_with("pypy3.")
}
};
if matches_implementation {
for suffix in suffixes.clone() {
let candidate = path.join(suffix.as_str());View on GitHub (pinned to 26f38c119c)
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.
Defensive patterns
Strategy: fallback
Validate before calling
# Before pointing ty at a prefix, sanity-check its site-packages layout:
import pathlib
for d in pathlib.Path(site_packages).iterdir():
if d.is_dir() and d.name == '':
print('malformed entry:', d) Prevention
- 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.
When it happens
Trigger: 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.
Common situations: 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.
Related errors
- Expected a UTF-8 working directory
- `object` should always be a non-generic class in typeshed
- extra use-def data should have been retained
- Expected a Title
- unexpected annotation type: {annotation:?}
AI-assisted analysis of astral-sh/ruff@26f38c119c (2026-09-05).
Data as JSON: /api/errors/9a536ccc13cd88d0.
Report an issue: GitHub.