{"record":{"id":"9500aa18a943e4a7","repo":"ClementTsang/bottom","slug":"unexpected-ps-output","errorCode":null,"errorMessage":"Unexpected 'ps' output","messagePattern":"Unexpected 'ps' output","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src/collection/processes/macos.rs","lineNumber":38,"sourceCode":"    fn backup_proc_cpu(pids: &[Pid]) -> io::Result<IntHashMap<Pid, f32>> {\n        let output = Command::new(\"ps\")\n            .args([\"-o\", \"pid=,pcpu=\", \"-p\"])\n            .arg(\n                // Has to look like this since otherwise, it you hit a `unstable_name_collisions`\n                // warning.\n                Itertools::intersperse(pids.iter().map(i32::to_string), \",\".to_string())\n                    .collect::<String>(),\n            )\n            .output()?;\n        let mut result = IntHashMap::default();\n        String::from_utf8_lossy(&output.stdout)\n            .split_whitespace()\n            .chunks(2)\n            .into_iter()\n            .for_each(|chunk| {\n                let chunk: Vec<&str> = chunk.collect();\n                if chunk.len() != 2 {\n                    panic!(\"Unexpected 'ps' output\");\n                }\n                let pid = chunk[0].parse();\n                let usage = chunk[1].parse();\n                if let (Ok(pid), Ok(usage)) = (pid, usage) {\n                    result.insert(pid, usage);\n                }\n            });\n        Ok(result)\n    }\n\n    fn parent_pid(process_val: &sysinfo::Process) -> Option<Pid> {\n        process_val\n            .parent()\n            .map(|p| p.as_u32() as _)\n            .or_else(|| fallback_macos_ppid(process_val.pid().as_u32() as _))\n    }\n}\n","sourceCodeStart":20,"sourceCodeEnd":56,"githubUrl":"https://github.com/ClementTsang/bottom/blob/b77d3175028849824e987c35177e8f61450d72e7/src/collection/processes/macos.rs#L20-L56","documentation":"backup_proc_cpu parses the output of a `ps` command (pid + cpu% pairs) on macOS. This panic fires when `ps` emits a line whose whitespace-split tokens do not pair up into even chunks of 2, or when a token count is odd, meaning `ps` produced output in an unexpected format.","triggerScenarios":"Calling process CPU collection when the `ps` binary on the system prints extra header lines, localized output, truncated/odd token counts, or any output where split_whitespace().chunks(2) yields a chunk with fewer than 2 tokens.","commonSituations":"Non-standard or busyboxed `ps` implementations, locale/HTML output options unsupported by the installed ps version, or `ps` emitting warning lines interleaved with data rows.","solutions":["Check what `ps -o pid= -o pcpu=` (or the exact command used) prints on the affected machine and confirm it emits clean two-column rows","Ensure the standard macOS/BSD ps is installed and first in PATH","Clear locale env vars (LC_ALL=C) that could change ps output format","Report/patch the parser to skip header lines instead of panicking on malformed chunks"],"exampleFix":"// before\n.for_each(|chunk| {\n    let chunk: Vec<&str> = chunk.collect();\n    if chunk.len() != 2 {\n        panic!(\"Unexpected 'ps' output\");\n    }\n// after\n.for_each(|chunk| {\n    let chunk: Vec<&str> = chunk.collect();\n    if chunk.len() != 2 {\n        eprintln!(\"skipping malformed ps output: {:?}\", chunk);\n        return;\n    }","handlingStrategy":"try-catch","validationCode":"// Rust: verify ps output shape before parsing\nlet out = Command::new(\"ps\").args([\"-o\", \"pid=,pcpu=\"]).output()?;\nlet ok = String::from_utf8_lossy(&out.stdout).lines().all(|l| l.split_whitespace().count() == 2);","typeGuard":null,"tryCatchPattern":"// This is a panic, not a Result: catch via catch_unwind or pre-validate\nlet r = std::panic::catch_unwind(|| backup_proc_cpu());\nmatch r { Ok(v) => v, Err(_) => default_map() }","preventionTips":["Run the exact ps command manually on target systems to confirm output shape","Set LC_ALL=C to stabilize ps output","Pin to standard macOS ps; avoid busybox/procps variants","Keep the library updated for ps-output parsing fixes"],"tags":["macos","processes","parsing","panic"],"backgroundTag":"unexpected-api-response-shape","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"}