ClementTsang/bottom · error · anyhow::Error

IOServiceGetMatchingServices failed, error code

Error message

IOServiceGetMatchingServices failed, error code {result}

What it means

get_disks enumerates physical disks on macOS via the IOKit function IOServiceGetMatchingServices (matching IOBlockStorageService). When the call returns anything other than KERN_SUCCESS, the kern_return_t error code is surfaced in this bail.

Solutions

  1. Check the numeric error code against IOKit kern_return_t values
  2. Run outside sandboxed/containerized environments with IOKit access
  3. Verify the process has entitlements/permissions for IOKit device queries
  4. Fall back to alternative disk enumeration (e.g. statfs on mount points)

Example fix

// before
let disks = io_stats()?;
// after
let disks = match io_stats() {
    Ok(d) => d,
    Err(e) => { log::warn!("iokit disk enumeration failed: {e}"); Vec::new() },
};
Defensive patterns

Strategy: try-catch

Validate before calling

// Pre-check that IOKit is reachable (outside sandbox) before harvesting
let has_iokit = std::path::Path::new("/System/Library/Extensions").exists();

Try / catch

match get_io_usage(&collector) {
    Ok(h) => h,
    Err(e) if e.to_string().starts_with("IOServiceGetMatchingServices failed") => {
        log::warn!("IOKit unavailable: {e}"); IoHarvest::default()
    },
    Err(e) => return Err(e),
}

Prevention

When it happens

Trigger: Calling disk I/O stats collection (io_stats -> get_disks) on macOS when IOKit cannot enumerate matching block storage services, e.g. due to IOKit master-port issues or sandboxing.

Common situations: Running in restricted environments (sandboxed apps, containers on macOS), IOKit service exhaustion, or permission restrictions on IOKit device registry access.

Related errors


AI-assisted analysis of ClementTsang/bottom@b77d317502 (2026-09-07). Data as JSON: /api/errors/25a95ac9906cc262. Report an issue: GitHub.

Appendix: source

Thrown at src/collection/disks/unix/macos/io_kit/io_disks.rs:22

use super::{IoIterator, bindings::*};

pub fn get_disks() -> anyhow::Result<IoIterator> {
    let mut media_iter: io_iterator_t = 0;

    // SAFETY: This is a safe syscall via IOKit, all the arguments should be
    // safe.
    let result = unsafe {
        IOServiceGetMatchingServices(
            kIOMasterPortDefault,
            IOServiceMatching(kIOMediaClass.as_ptr().cast()),
            &mut media_iter,
        )
    };

    if result == kern_return::KERN_SUCCESS {
        Ok(media_iter.into())
    } else {
        bail!("IOServiceGetMatchingServices failed, error code {result}");
    }
}

View on GitHub (pinned to b77d317502)