ClementTsang/bottom · warning
missing key
Error message
missing key
What it means
macOS I/O Kit helper `get_dict(dict, raw_key)` looks up `raw_key` in a `CFDictionary` of an IOService/IORegistryEntry and bails with 'missing key' when the key is absent or the value cannot be wrapped as a CFDictionary. Called from `get_device_io`, it means the expected IORegistry dictionary entry (e.g. statistics/protocol characteristics) does not exist for this device.
Solutions
- Treat missing keys as optional data — skip the device or default the value rather than failing the whole collection
- Verify the key string matches the exact IORegistry key name (case-sensitive) for your macOS version
- Check the device in IORegistryExplorer to confirm which keys it actually publishes
- Filter device classes (only physical/internal disks) before querying IOStatistics
Example fix
// before
let dict = io_object::get_dict(&dict, "kIOPropertyNVMeSMARTData")?;
// after
let smart = match io_object::get_dict(&dict, "kIOPropertyNVMeSMARTData") {
Ok(d) => d,
Err(_) => {
// device does not expose this key; continue with defaults
Default::default()
},
}; Defensive patterns
Strategy: fallback
Validate before calling
// Confirm the key exists before requesting a dictionary value
let key = core_foundation::string::CFString::new("target_key");
if dict.find(key).is_some() {
let d = io_object::get_dict(&dict, "target_key")?;
} else {
// device does not publish this key; use defaults
} Type guard
fn optional_dict(dict: &CFDictionary<CFString, CFType>, key: &str)
-> Option<CFDictionary<CFString, CFType>> {
io_object::get_dict(dict, key).ok()
} Try / catch
let io_dict = match io_object::get_dict(&entry_dict, "IOStatistics") {
Ok(d) => Some(d),
Err(e) if e.to_string() == "missing key" => None,
Err(e) => return Err(e),
}; Prevention
- Inspect the device in IORegistryExplorer to confirm which keys it publishes
- Treat IOKit keys as optional — virtual/USB disks often lack them
- Pin key names per macOS version; they can change between releases
- Filter to device classes known to expose the statistics you need
When it happens
Trigger: `get_device_io` querying a disk whose IORegistry entry lacks the expected dictionary key; the value under the key exists but is not a CFDictionary; device hardware/firmware does not publish the expected IORegistry data; virtual or external drives missing the key.
Common situations: Running on Macs with virtualized disks (AVFarming, VMs) or USB bridges that do not expose IORegistry statistics; macOS version differences in IORegistry layout; requesting keys from non-physical devices.
Understand the failure class
Background: 'Could not be found', 'does not exist', 'not found in database': the resource-not-found family when an ID, slug, key, or URI lookup comes back empty — this error's family across 20 libraries.
Related errors
- IOServiceGetMatchingServices failed, error code
- IORegistryEntryCreateCFProperties failed, error code
- IORegistryEntryGetParentEntry failed, error code
- Unexpected 'ps' output
- Unsupported OS
AI-assisted analysis of ClementTsang/bottom@b77d317502 (2026-09-07).
Data as JSON: /api/errors/934f676fe545d2dc.
Report an issue: GitHub.
Appendix: source
Thrown at src/collection/disks/unix/macos/io_kit/io_object.rs:111
) -> anyhow::Result<CFDictionary<CFString, CFType>> {
let key = CFString::from_static_string(raw_key);
dict.find(&key)
.map(|value_ref| {
// SAFETY: Only used for debug asserts, system API call that should
// be safe.
unsafe {
debug_assert!(value_ref.type_of() == CFDictionaryGetTypeID());
}
// "Casting" `CFDictionary<*const void, *const void>` into a needed
// dict type
let ptr = value_ref.to_void() as CFDictionaryRef;
// SAFETY: System API call, it should be safe?
unsafe { CFDictionary::wrap_under_get_rule(ptr) }
})
.ok_or_else(|| anyhow!("missing key"))
}
pub fn get_i64(
dict: &CFDictionary<CFString, CFType>, raw_key: &'static str,
) -> anyhow::Result<i64> {
let key = CFString::from_static_string(raw_key);
dict.find(&key)
.and_then(|value_ref| {
// SAFETY: Only used for debug asserts, system API call that should
// be safe.
unsafe {
debug_assert!(value_ref.type_of() == CFNumberGetTypeID());
}
value_ref.downcast::<CFNumber>()
})
.and_then(|number| number.to_i64())
.ok_or_else(|| anyhow!("missing key"))View on GitHub (pinned to b77d317502)