{"record":{"id":"47761fb10b649830","repo":"rustfs/rustfs","slug":"failed-to-parse-token-as-u64-e","errorCode":null,"errorMessage":"failed to parse '{token}' as u64: {e}","messagePattern":"failed to parse '(.+?)' as u64: (.+?)","errorType":"exception","errorClass":"std::io::Error","httpStatus":null,"severity":"warning","filePath":"crates/utils/src/os/linux.rs","lineNumber":364,"sourceCode":"\nfn read_stat(file_name: &str) -> std::io::Result<Vec<u64>> {\n    // Open file\n    let path = Path::new(file_name);\n    let file = File::open(path)?;\n\n    // Create a BufReader\n    let reader = io::BufReader::new(file);\n\n    // Read first line\n    let mut stats = Vec::new();\n    if let Some(line) = reader.lines().next() {\n        let line = line?;\n        // Split line and parse as u64\n        // https://rust-lang.github.io/rust-clippy/master/index.html#trim_split_whitespace\n        for token in line.split_whitespace() {\n            let ui64: u64 = token\n                .parse()\n                .map_err(|e| Error::new(ErrorKind::InvalidData, format!(\"failed to parse '{token}' as u64: {e}\")))?;\n            stats.push(ui64);\n        }\n    }\n\n    Ok(stats)\n}\n\n#[cfg(test)]\nmod tests {\n    use super::*;\n    use tempfile::tempdir;\n\n    #[test]\n    fn normalize_partition_device_to_parent_disk() {\n        let dir = tempdir().unwrap();\n        let block = dir.path().join(\"block\");\n        let disk = block.join(\"nvme0n1\");\n        let partition = disk.join(\"nvme0n1p1\");","sourceCodeStart":346,"sourceCodeEnd":382,"githubUrl":"https://github.com/rustfs/rustfs/blob/35af688cd9d41b4346fbe27dcf7250ba72046c1f/crates/utils/src/os/linux.rs#L346-L382","documentation":"read_stat (crates/utils/src/os/linux.rs:364) splits the first line of a sysfs stats file on whitespace and parses every token as u64; any non-numeric token returns InvalidData naming the token. The /sys/dev/block/*/stat ABI is all-numeric, so this fires when the file's layout differs from expectations or the path points at the wrong file.","triggerScenarios":"A stats line containing a non-numeric field — a device-name column or '-' placeholder where a counter should be — or calling read_stat on a file whose format is not a plain numeric row.","commonSituations":"Kernel-version differences in sysfs layout; a stale major:minor mapping after device changes; virtualized environments exposing unusual sysfs content.","solutions":["Manually inspect the file's first line and compare it with the expected numeric layout.","Verify the major:minor to path mapping (/sys/dev/block/MAJ:MIN/stat) is current — device numbers change across reboots or udev re-enumeration.","Skip non-numeric columns defensively if only specific indices are consumed."],"exampleFix":null,"handlingStrategy":"fallback","validationCode":"let first = std::fs::read_to_string(path)?.lines().next().unwrap_or_default();\nlet all_numeric = first.split_whitespace().all(|t| t.parse::<u64>().is_ok());\nif !all_numeric { /* skip or trim non-numeric columns */ }","typeGuard":null,"tryCatchPattern":"match read_stat(path) {\n    Err(e) if e.kind() == std::io::ErrorKind::InvalidData => { warn!(\"unparseable stats file: {e}\"); vec![] }\n    r => r.unwrap_or_default(),\n}","preventionTips":["Pin the expected sysfs field layout per kernel version instead of assuming one shape.","Re-resolve major:minor to a sysfs path after device changes rather than caching it.","Log the offending token so layout changes are diagnosable from logs."],"tags":["linux","sysfs","parsing","disk-stats"],"backgroundTag":"sysfs-parse-error","analyzedSha":"35af688cd9d41b4346fbe27dcf7250ba72046c1f","analyzedAt":"2026-08-20T21:57:04.799Z","contentChangedAt":"2026-08-20T21:57:04.799Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}