firecracker-microvm/firecracker · error

Bus ranges and devices out of sync

Error message

Bus ranges and devices out of sync

What it means

Error "Bus ranges and devices out of sync" thrown in firecracker-microvm/firecracker.

Solutions

  1. Keep the bus range list and device list updates in a single atomic operation so they cannot diverge.
  2. Check the bus insert/remove logic for a path that updates one list without the other.

When it happens

Trigger: Thrown at src/vmm/src/vstate/bus.rs:201 when the library encounters an invalid state.

Common situations: See trigger scenarios.


AI-assisted analysis of firecracker-microvm/firecracker@23b09b943f (2026-08-19). Data as JSON: /api/errors/1f60050fb9520db5. Report an issue: GitHub.

Appendix: source

Thrown at src/vmm/src/vstate/bus.rs:207

        addr: u64,
        len: u64,
        f: impl FnOnce(&mut dyn BusDevice, u64, u64) -> T,
    ) -> Result<T, BusError> {
        let access = BusRange::new(addr, len)?;

        let devices = self.devices.read().unwrap();
        let (base, slot) = {
            let ranges = self.ranges.read().unwrap();
            match ranges.range(..=access).next_back() {
                // `range` query already guarantees `range.base() <= addr`.
                Some((range, &slot)) if access.end() <= range.end() => (range.base(), slot),
                _ => return Err(BusError::MissingAddressRange),
            }
        };

        let device = devices
            .get(slot)
            .expect("Bus ranges and devices out of sync");

        let Some(device) = device.upgrade() else {
            return Err(BusError::MissingAddressRange);
        };

        let mut locked = device.lock().unwrap();
        let offset = addr - base;
        Ok(f(&mut *locked, base, offset))
    }

    /// Relocate an existing device mapping from `old_base` to `new_base`.
    /// Only the `ranges` lock is taken, not the `devices` lock.
    pub fn move_range(&self, old_base: u64, new_base: u64, len: u64) -> Result<(), BusError> {
        let old_range = BusRange::new(old_base, len)?;
        let new_range = BusRange::new(new_base, len)?;

        let mut ranges = self.ranges.write().unwrap();

View on GitHub (pinned to 23b09b943f)