{"record":{"id":"158f12fc9230be8f","repo":"ClementTsang/bottom","slug":"invalid-handle-value","errorCode":null,"errorMessage":"Invalid handle value: {:?}","messagePattern":"Invalid handle value: (.+?)","errorType":"error_code","errorClass":"anyhow::Error","httpStatus":null,"severity":"error","filePath":"src/collection/disks/windows/bindings.rs","lineNumber":59,"sourceCode":"        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,\n            FILE_SHARE_READ | FILE_SHARE_WRITE,\n            None,\n            OPEN_EXISTING,\n            FILE_FLAGS_AND_ATTRIBUTES(0),\n            Some(Foundation::HANDLE::default()),\n        )?\n    };\n\n    if h_device.is_invalid() {\n        bail!(\"Invalid handle value: {:?}\", io::Error::last_os_error());\n    }\n\n    let mut disk_performance = DISK_PERFORMANCE::default();\n    let mut bytes_returned = 0;\n\n    // SAFETY: This should be safe, we'll manually check the results and the\n    // arguments should be valid.\n    let ret = unsafe {\n        DeviceIoControl(\n            h_device,\n            IOCTL_DISK_PERFORMANCE,\n            None,\n            0,\n            Some(&mut disk_performance as *mut _ as _),\n            mem::size_of::<DISK_PERFORMANCE>() as u32,\n            Some(&mut bytes_returned),\n            None,\n        )","sourceCodeStart":41,"sourceCodeEnd":77,"githubUrl":"https://github.com/ClementTsang/bottom/blob/b77d3175028849824e987c35177e8f61450d72e7/src/collection/disks/windows/bindings.rs#L41-L77","documentation":"In volume_io, CreateFileW opened the volume path (\\\\.\\C:) but returned a handle that fails is_invalid() (INVALID_HANDLE_VALUE), so the code bails with the last OS error. The library treats an invalid volume handle as fatal because the subsequent DeviceIoControl(IOCTL_DISK_PERFORMANCE) call needs a valid handle. It typically means the volume path could not be opened even though the Win32 call itself reported success-shaped behavior.","triggerScenarios":"CreateFileW on a volume GUID path returns INVALID_HANDLE_VALUE — e.g. the volume has been removed/dismounted between FindFirstVolumeW enumeration and the open, the path lacks the correct \\\\?\\ volume GUID prefix, or access to the device is denied in a way surfaced as an invalid handle.","commonSituations":"Enumerating disk performance stats on machines where a USB/network volume disappears mid-scan; running in environments (services, containers, restricted tokens) without rights to open volume devices; calling volume_io with a hand-crafted path missing the trailing-backslash-to-NUL normalization the function performs.","solutions":["Check the logged io::Error::last_os_error() for the underlying Win32 error code (e.g. ERROR_ACCESS_DENIED, ERROR_FILE_NOT_FOUND) and fix that condition","Re-run the collection; transient cases (volume removed mid-iteration) resolve on the next pass","Ensure the process runs with sufficient privileges (Administrator) to open volume devices","Filter out volumes that fail to open instead of failing the entire all_volume_io scan"],"exampleFix":"// before\nif h_device.is_invalid() {\n    bail!(\"Invalid handle value: {:?}\", io::Error::last_os_error());\n}\n// after\nif h_device.is_invalid() {\n    eprintln!(\"skipping volume {}: {:?}\", volume.display(), io::Error::last_os_error());\n    return Ok(None); // or continue to the next volume\n}","handlingStrategy":"try-catch","validationCode":"// Windows: check the volume path is a \\\\?\\Volume{...}\\ device path before querying\nfn is_volume_guid_path(p: &str) -> bool {\n    p.starts_with(\"\\\\\\\\?\\\\Volume{\") && p.ends_with(\"\\\\\")\n}","typeGuard":"fn handle_valid(h: HANDLE) -> bool { !h.is_invalid() }","tryCatchPattern":"match all_volume_io() {\n    Ok(results) => results,\n    Err(e) => { log::warn!(\"volume io unavailable: {e:?}\"); Vec::new() }\n}","preventionTips":["Run collectors with enough privilege to open volume devices","Re-enumerate volumes immediately before querying instead of caching paths","Skip failed volumes rather than failing the whole scan"],"tags":["windows","win32","disk-io","handle"],"backgroundTag":"invalid-argument-value","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"}