ClementTsang/bottom · error · anyhow::Error
IORegistryEntryGetParentEntry failed, error code
Error message
IORegistryEntryGetParentEntry failed, error code {result}. What it means
service_parent walks up the IOKit service plane (kIOServicePlane) via IORegistryEntryGetParentEntry to reach the parent of an IOKit entry (e.g. from IOSBlockStorageService up to its driver). A non-KERN_SUCCESS result is converted into this error.
Solutions
- Treat missing parents as a traversal boundary and stop walking up for that entry
- Re-run disk enumeration to get fresh, valid IOKit entries
- Inspect the kern_return_t code to distinguish 'no parent' from invalid entry
- Skip that device's stats instead of failing the whole harvest
Example fix
// before
let parent = entry.service_parent()?;
// after
let parent = match entry.service_parent() {
Ok(p) => p,
Err(e) => { log::debug!("no parent entry, stopping traversal: {e}"); return None },
}; Defensive patterns
Strategy: try-catch
Try / catch
let parent = match entry.service_parent() {
Ok(p) => Some(p),
Err(e) if e.to_string().contains("IORegistryEntryGetParentEntry") => {
log::debug!("traversal boundary: {e}"); None
},
Err(e) => return Err(e),
}; Prevention
- Treat a missing parent as end-of-traversal, not a fatal error
- Refresh the device iterator on every collection cycle
- Don't reuse io_object handles across sweeps
- Record kern_return_t codes for support diagnostics
When it happens
Trigger: Calling service_parent() on an io_object that has no parent in the IOService plane or is not a valid registry entry — typically during the disk statistics traversal.
Common situations: Hot-unplugged devices mid-enumeration, synthetic/edge entries lacking parents, or entries from a stale iterator after system changes.
Related errors
- IOServiceGetMatchingServices failed, error code
- IORegistryEntryCreateCFProperties failed, error code
- missing key
- Unexpected 'ps' output
- Unsupported OS
AI-assisted analysis of ClementTsang/bottom@b77d317502 (2026-09-07).
Data as JSON: /api/errors/b32c2e87f2fa133d.
Report an issue: GitHub.
Appendix: source
Thrown at src/collection/disks/unix/macos/io_kit/io_object.rs:60
} else {
let props = props.assume_init();
Ok(CFMutableDictionary::wrap_under_create_rule(props).to_immutable())
}
}
}
/// Gets the [`kIOServicePlane`] parent [`io_object_t`] for this
/// [`io_object_t`], if there is one.
pub fn service_parent(&self) -> anyhow::Result<IoObject> {
let mut parent: io_registry_entry_t = 0;
// SAFETY: IOKit call, the arguments should be safe.
let result = unsafe {
IORegistryEntryGetParentEntry(self.0, kIOServicePlane.as_ptr().cast(), &mut parent)
};
if result != kern_return::KERN_SUCCESS {
bail!("IORegistryEntryGetParentEntry failed, error code {result}.")
} else {
Ok(parent.into())
}
}
// pub fn conforms_to_block_storage_driver(&self) -> bool {
// // SAFETY: IOKit call, the arguments should be safe.
// let result =
// unsafe { IOObjectConformsTo(self.0,
// "IOBlockStorageDriver\0".as_ptr().cast()) };
// result != 0
// }
}
impl From<io_object_t> for IoObject {
fn from(obj: io_object_t) -> IoObject {
IoObject(obj)View on GitHub (pinned to b77d317502)