{"record":{"id":"bfe87d094d3d3e23","repo":"ClementTsang/bottom","slug":"expects-a-directory-to-be-passed-in","errorCode":null,"errorMessage":"Expects a directory to be passed in.","messagePattern":"Expects a directory to be passed in\\.","errorType":"error_code","errorClass":"anyhow::Error","httpStatus":null,"severity":"error","filePath":"src/collection/disks/windows/bindings.rs","lineNumber":31,"sourceCode":"    Storage::FileSystem::{\n        CreateFileW, FILE_FLAGS_AND_ATTRIBUTES, FILE_SHARE_READ, FILE_SHARE_WRITE,\n        FindFirstVolumeW, FindNextVolumeW, FindVolumeClose, GetVolumeNameForVolumeMountPointW,\n        OPEN_EXISTING,\n    },\n    System::{\n        IO::DeviceIoControl,\n        Ioctl::{DISK_PERFORMANCE, IOCTL_DISK_PERFORMANCE},\n    },\n};\n\n/// Returns the I/O for a given volume.\n///\n/// Based on [psutil's implementation](https://github.com/giampaolo/psutil/blob/52fe5517f716dedf9c9918e56325e49a49146130/psutil/arch/windows/disk.c#L78-L83)\n/// and [heim's implementation](https://github.com/heim-rs/heim/blob/master/heim-disk/src/sys/windows/bindings/perf.rs).\nfn volume_io(volume: &Path) -> anyhow::Result<DISK_PERFORMANCE> {\n    if volume.is_file() {\n        // We assume the volume is a directory, so bail ASAP if it isn't.\n        bail!(\"Expects a directory to be passed in.\");\n    }\n\n    let volume = {\n        let mut wide_path = volume.as_os_str().encode_wide().collect::<Vec<_>>();\n\n        // We replace the trailing backslash and replace it with a \\0.\n        wide_path.pop();\n        wide_path.push(0x0000);\n\n        wide_path\n    };\n\n    // SAFETY: API call, arguments should be correct. We must also check after\n    // the call to ensure it is valid.\n    let h_device = unsafe {\n        CreateFileW(\n            windows::core::PCWSTR(volume.as_ptr()),\n            0,","sourceCodeStart":13,"sourceCodeEnd":49,"githubUrl":"https://github.com/ClementTsang/bottom/blob/b77d3175028849824e987c35177e8f61450d72e7/src/collection/disks/windows/bindings.rs#L13-L49","documentation":"volume_io on Windows opens a volume path (e.g. \\\\.\\C:\\) with CreateFile to query DISK_PERFORMANCE via DeviceIoControl. The function expects the input to be a volume directory-style path; if volume.is_file() returns true, the input is rejected as it cannot be a volume root.","triggerScenarios":"Calling volume_io (via all_volume_io) with a path that the system classifies as a regular file rather than a directory/volume root, e.g. passing a drive path without trailing separator or an actual file path.","commonSituations":"Passing 'C:' without a trailing backslash, passing mounted folder paths or file paths instead of volume roots, or misconfigured volume path lists.","solutions":["Ensure the path passed is a volume root ending with a path separator (e.g. C:\\)","Only pass paths obtained from GetLogicalDrives / volume enumeration, not arbitrary files","Normalize the path to its root (path.ancestors().last() or Path::new(\"C:\\\\\"))","Filter enumerated paths with is_dir() checks before calling"],"exampleFix":"// before\nlet perf = volume_io(&Path::new(\"C:\"))?;\n// after\nlet root = Path::new(\"C:\\\");\nassert!(root.is_dir());\nlet perf = volume_io(root)?;","handlingStrategy":"validation","validationCode":"// Ensure the path is a volume root directory with a trailing separator\nlet p = std::path::Path::new(\"C:\\\");\nif p.is_file() { panic!(\"not a volume root\"); }\nlet ends_with_sep = p.as_os_str().to_string_lossy().ends_with('\\\\');","typeGuard":"fn is_volume_root(p: &std::path::Path) -> bool {\n    p.is_dir() && p.parent().is_none() && p.as_os_str().to_string_lossy().ends_with('\\\\')\n}","tryCatchPattern":"match all_volume_io() {\n    Ok(map) => map,\n    Err(e) if e.to_string().contains(\"Expects a directory\") => {\n        log::warn!(\"bad volume path given: {e}\"); Default::default()\n    },\n    Err(e) => return Err(e),\n}","preventionTips":["Always pass volume roots like C:\\\\ with a trailing backslash","Derive volume paths from GetLogicalDrives/GetVolumePathNamesForVolumeName, not user input","Check is_dir() before invoking volume IO queries","Normalize drive letters to their root via path ancestors"],"tags":["windows","disks","io","invalid-argument"],"backgroundTag":"path-is-not-a-directory","analyzedSha":"b77d3175028849824e987c35177e8f61450d72e7","analyzedAt":"2026-09-07T14:53:21.246Z","contentChangedAt":"2026-09-07T14:53:21.246Z","schemaVersion":2},"datasetVersion":"2026-09-16T04:17:20.429Z"}