{"record":{"id":"4eec1d981eadec3a","repo":"ClementTsang/bottom","slug":"pid-for-pid-path-was-not-found","errorCode":null,"errorMessage":"PID for {pid_path:?} was not found","messagePattern":"PID for (.+?) was not found","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src/collection/processes/linux/process.rs","lineNumber":301,"sourceCode":"\n        let pid_dir = rustix::fs::openat(\n            rustix::fs::CWD,\n            pid_path.as_path(),\n            OFlags::PATH | OFlags::DIRECTORY | OFlags::CLOEXEC,\n            Mode::empty(),\n        )?;\n\n        let pid = pid_path\n            .as_path()\n            .components()\n            .next_back()\n            .and_then(|s| s.to_string_lossy().parse::<Pid>().ok())\n            .or_else(|| {\n                rustix::fs::readlinkat(rustix::fs::CWD, pid_path.as_path(), vec![])\n                    .ok()\n                    .and_then(|s| s.to_string_lossy().parse::<Pid>().ok())\n            })\n            .ok_or_else(|| anyhow!(\"PID for {pid_path:?} was not found\"))?;\n\n        let uid = {\n            let metadata = rustix::fs::fstat(&pid_dir);\n            match metadata {\n                Ok(md) => Some(md.st_uid),\n                Err(_) => None,\n            }\n        };\n\n        let mut root = pid_path;\n\n        // NB: Whenever you add a new stat, make sure to pop the root and clear\n        // the buffer!\n\n        // Stat is pretty long, do this first to pre-allocate up-front.\n        let stat =\n            open_at(&mut root, \"stat\", &pid_dir).and_then(|file| Stat::from_file(file, buffer))?;\n        reset(&mut root, buffer);","sourceCodeStart":283,"sourceCodeEnd":319,"githubUrl":"https://github.com/ClementTsang/bottom/blob/b77d3175028849824e987c35177e8f61450d72e7/src/collection/processes/linux/process.rs#L283-L319","documentation":"When building a Process from a /proc/<pid> directory, the PID is recovered from the directory entry: either the file name itself or, for numeric-task threads, the target of the symlink via readlinkat. If neither yields a value parseable as a Pid, the library raises this error because a process cannot be represented without its PID.","triggerScenarios":"Calling Process::from_path on a directory whose name is non-numeric and whose readlink does not resolve to a numeric PID — e.g. a /proc/<pid>/task entry that vanished, a fake/stub procfs, or a directory with an unexpected name.","commonSituations":"Scanning /proc/[pid]/task while threads terminate (dirfd points at a removed entry); running in restricted containers where readlink fails on procfs; non-standard procfs mounts or mocked filesystems used in tests.","solutions":["Skip the unreadable entry during enumeration — the thread/process likely exited between listing and opening.","Verify the path is a genuine /proc/<pid> or /proc/<pid>/task/<tid> directory before calling Process::from_path.","Check that the process still exists (readdir race); re-scan /proc to refresh the entry list."],"exampleFix":"// before\nlet proc = Process::from_path(pid_dir).unwrap();\n// after\nmatch Process::from_path(&pid_dir) {\n    Ok(p) => processes.push(p),\n    Err(e) if e.to_string().contains(\"was not found\") => {\n        // thread/process vanished mid-scan; skip it\n    }\n    Err(e) => return Err(e.into()),\n}","handlingStrategy":"fallback","validationCode":"fn pid_from_dir(path: &Path) -> Option<Pid> {\n    path.file_name()\n        .and_then(|n| n.to_str())\n        .and_then(|n| n.parse::<Pid>().ok())\n        .or_else(|| std::fs::read_link(path).ok()\n            .and_then(|t| t.to_str().and_then(|s| s.parse().ok())))\n}\nif pid_from_dir(&dir).is_none() { skip_entry(); }","typeGuard":"fn dir_is_process(dir: &Path) -> bool {\n    dir.file_name()\n        .and_then(|n| n.to_str())\n        .map(|n| n.parse::<i32>().is_some())\n        .unwrap_or(false)\n}","tryCatchPattern":"match Process::from_path(&pid_dir) {\n    Ok(p) => Some(p),\n    Err(e) if e.to_string().contains(\"was not found\") => None,\n    Err(e) => return Err(e.into()),\n}","preventionTips":["Filter directory listings to numeric names before constructing Processes","Expect races: any /proc entry may disappear between readdir and open; skip those","In containers, verify /proc is a real procfs mount, not a masked or stubbed path"],"tags":["linux","procfs","processes","pid"],"backgroundTag":"entity-not-found","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"}