astral-sh/ruff · error · io::Error

directory listings are only supported for system paths

Error message

directory listings are only supported for system paths

What it means

This io::Error (kind InvalidInput) is returned by ty's `directory_listing` salsa query when the directory's `FilePath` is `Vendored` or `SystemVirtual` instead of `System`. Directory enumeration is only implemented for real system paths, so all other path kinds are rejected with this message.

Source

Thrown at crates/ruff_db/src/files/directory.rs:113

    db: &'db dyn Db,
    path: &SystemPath,
) -> Result<&'db DirectoryListing, DirectoryListingError> {
    let directory = system_path_to_directory(db, path)?;
    directory_listing_query(db, directory).map_err(Clone::clone)
}

#[salsa::tracked(returns(as_ref), heap_size=ruff_memory_usage::heap_size)]
fn directory_listing_query(
    db: &dyn Db,
    directory: File,
) -> Result<DirectoryListing, DirectoryListingError> {
    let _ = directory.revision(db);
    let _ = directory.permissions(db);

    let path = match directory.path(db) {
        FilePath::System(path) => path,
        FilePath::Vendored(_) | FilePath::SystemVirtual(_) => {
            return Err(std::io::Error::new(
                std::io::ErrorKind::InvalidInput,
                "directory listings are only supported for system paths",
            )
            .into());
        }
    };

    let mut entries = db
        .system()
        .read_directory(path)?
        .filter_map(|entry| {
            let entry = entry.ok()?;
            let file_type = entry.file_type();
            let path = entry.into_path();
            let name = path.file_name()?;
            Some((CompactString::from(name), file_type))
        })
        .collect::<Vec<_>>();

View on GitHub (pinned to 15f3fe6b15)

Solutions

  1. Guard the call: only request a directory listing when `matches!(dir.path(db), FilePath::System(_))`
  2. Return an empty listing or handle the error gracefully for vendored/virtual paths
  3. If the path should be a real directory, fix the path construction/resolution

Example fix

// before
let listing = directory_listing(db, dir)?;
// after
let listing = match dir.path(db) {
    FilePath::System(_) => directory_listing(db, dir)?,
    _ => DirectoryListing::default(), // vendored/virtual dirs are not enumerable
};
Defensive patterns

Strategy: type-guard

Validate before calling

if not isinstance(dir.path(db), FilePath.System):
    return empty_listing()

Type guard

fn is_listable(dir: &Directory<'_>, db: &dyn Files) -> bool {
    matches!(dir.path(db), FilePath::System(_))
}

Try / catch

match directory_listing(db, dir) {
    Err(err) if err.kind() == std::io::ErrorKind::InvalidInput => Ok(DirectoryListing::default()),
    Err(err) => Err(err),
    Ok(listing) => Ok(listing),
}

Prevention

When it happens

Trigger: Requesting `directory_listing(db, dir)` where `dir.path(db)` is a vendored (typeshed-internal) or system-virtual path, e.g. autocomplete enumerating a stub package directory.

Common situations: Completion/resolve code listing directories inside vendored typeshed, tests exercising virtual file systems, callers not filtering path kinds before listing.

Related errors


AI-assisted analysis of astral-sh/ruff@15f3fe6b15 (2026-09-05). Data as JSON: /api/errors/53d6d8c6574277e1. Report an issue: GitHub.