{"record":{"id":"53d6d8c6574277e1","repo":"astral-sh/ruff","slug":"directory-listings-are-only-supported-for-system-p","errorCode":null,"errorMessage":"directory listings are only supported for system paths","messagePattern":"directory listings are only supported for system paths","errorType":"error_code","errorClass":"io::Error","httpStatus":null,"severity":"error","filePath":"crates/ruff_db/src/files/directory.rs","lineNumber":113,"sourceCode":"    db: &'db dyn Db,\n    path: &SystemPath,\n) -> Result<&'db DirectoryListing, DirectoryListingError> {\n    let directory = system_path_to_directory(db, path)?;\n    directory_listing_query(db, directory).map_err(Clone::clone)\n}\n\n#[salsa::tracked(returns(as_ref), heap_size=ruff_memory_usage::heap_size)]\nfn directory_listing_query(\n    db: &dyn Db,\n    directory: File,\n) -> Result<DirectoryListing, DirectoryListingError> {\n    let _ = directory.revision(db);\n    let _ = directory.permissions(db);\n\n    let path = match directory.path(db) {\n        FilePath::System(path) => path,\n        FilePath::Vendored(_) | FilePath::SystemVirtual(_) => {\n            return Err(std::io::Error::new(\n                std::io::ErrorKind::InvalidInput,\n                \"directory listings are only supported for system paths\",\n            )\n            .into());\n        }\n    };\n\n    let mut entries = db\n        .system()\n        .read_directory(path)?\n        .filter_map(|entry| {\n            let entry = entry.ok()?;\n            let file_type = entry.file_type();\n            let path = entry.into_path();\n            let name = path.file_name()?;\n            Some((CompactString::from(name), file_type))\n        })\n        .collect::<Vec<_>>();","sourceCodeStart":95,"sourceCodeEnd":131,"githubUrl":"https://github.com/astral-sh/ruff/blob/15f3fe6b15a5f00172f34b0f542f8ea277f5a586/crates/ruff_db/src/files/directory.rs#L95-L131","documentation":"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.","triggerScenarios":"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.","commonSituations":"Completion/resolve code listing directories inside vendored typeshed, tests exercising virtual file systems, callers not filtering path kinds before listing.","solutions":["Guard the call: only request a directory listing when `matches!(dir.path(db), FilePath::System(_))`","Return an empty listing or handle the error gracefully for vendored/virtual paths","If the path should be a real directory, fix the path construction/resolution"],"exampleFix":"// before\nlet listing = directory_listing(db, dir)?;\n// after\nlet listing = match dir.path(db) {\n    FilePath::System(_) => directory_listing(db, dir)?,\n    _ => DirectoryListing::default(), // vendored/virtual dirs are not enumerable\n};","handlingStrategy":"type-guard","validationCode":"if not isinstance(dir.path(db), FilePath.System):\n    return empty_listing()","typeGuard":"fn is_listable(dir: &Directory<'_>, db: &dyn Files) -> bool {\n    matches!(dir.path(db), FilePath::System(_))\n}","tryCatchPattern":"match directory_listing(db, dir) {\n    Err(err) if err.kind() == std::io::ErrorKind::InvalidInput => Ok(DirectoryListing::default()),\n    Err(err) => Err(err),\n    Ok(listing) => Ok(listing),\n}","preventionTips":["Only enumerate directories known to live on the real file system","Model vendored/virtual packages with stub data instead of directory scans","Filter path kinds early in completion/resolve pipelines"],"tags":["filesystem","directory","unsupported"],"backgroundTag":"unsupported-file-system-operation","analyzedSha":"15f3fe6b15a5f00172f34b0f542f8ea277f5a586","analyzedAt":"2026-09-05T10:32:37.492Z","contentChangedAt":"2026-09-05T10:32:37.492Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}