Description
The std::fs::ReadDir
iterator, returned by a call to std::fs::read_dir
, can return an error forever in some cases on Windows. Notably, this can happen when reading a directory that is on a removable device (such as an usb drive), and removing this device:
fn main() {
for entry in std::fs::read_dir("E:").unwrap() {
println!("entry: {:?}", entry);
std::thread::sleep(std::time::Duration::from_millis(500));
}
}
With this scenario:
- Mount an USB drive that contains a hundred file onto E:
- Run the test
- While the test is running, unplug the drive
This test gives something like this:
entry: Ok(DirEntry("E:file1"))
entry: Ok(DirEntry("E:file2"))
entry: Ok(DirEntry("E:file3"))
entry: Ok(DirEntry("E:file4"))
entry: Ok(DirEntry("E:file5"))
entry: Err(Os { code: 21, kind: Uncategorized, message: "The device is not ready." })
entry: Err(Os { code: 21, kind: Uncategorized, message: "The device is not ready." })
entry: Err(Os { code: 21, kind: Uncategorized, message: "The device is not ready." })
entry: Err(Os { code: 21, kind: Uncategorized, message: "The device is not ready." })
entry: Err(Os { code: 21, kind: Uncategorized, message: "The device is not ready." })
entry: Err(Os { code: 21, kind: Uncategorized, message: "The device is not ready." })
entry: Err(Os { code: 21, kind: Uncategorized, message: "The device is not ready." })
entry: Err(Os { code: 21, kind: Uncategorized, message: "The device is not ready." })
entry: Err(Os { code: 21, kind: Uncategorized, message: "The device is not ready." })
...
I have also observed the error ERROR_WRONG_DISK (code 34) and the error ERROR_FILE_INVALID (code 1006) under this scenario.
This feels a bit similar to #50619 which was for a similar issue (infinite loop on the iterator) but on Linux.
ReadDir
is documented as follows:
This io::Result will be an Err if there’s some sort of intermittent IO error during iteration.
However this error is not intermittent: replugging the usb drive will not make the iteration start returning OK values.
I'm not sure how easy this issue is to fix however. Maybe detecting the error code to distinguish intermittent errors from non intermittent ones, but just this simple test can return at least 3 different error codes in my tests, so that seems hard do properly.
Meta
rustc --version --verbose
:
rustc 1.87.0 (17067e9ac 2025-05-09)
binary: rustc
commit-hash: 17067e9ac6d7ecb70e50f92c1944e545188d2359
commit-date: 2025-05-09
host: x86_64-pc-windows-msvc
release: 1.87.0
LLVM version: 20.1.1
Also tested on nightly, same results:
rustc 1.89.0-nightly (e703dff8f 2025-06-11)
binary: rustc
commit-hash: e703dff8fe220b78195c53478e83fb2f68d8499c
commit-date: 2025-06-11
host: x86_64-pc-windows-msvc
release: 1.89.0-nightly
LLVM version: 20.1.5