embassy-rs/embassy · error

out of memory

Error message

out of memory

What it means

The nrf91 driver's internal bump Allocator panicked because alloc_bytes() was asked for a chunk larger than the remaining bytes between its start and end pointers. The driver pre-allocates a fixed memory pool for packet buffers, and a requested allocation exceeded the whole (remaining) pool. This is a build/config sizing problem: the static pool is too small for the requested buffers.

Solutions

  1. Increase the memory pool size passed when constructing the Allocator (and free up RAM elsewhere) so it can hold all configured buffers
  2. Reduce configured buffer count or MTU in the driver config so total required bytes fit the pool
  3. Compute the required pool size (buffers * buffer_size, plus allocator alignment) and size the static region accordingly
  4. Check for regressions after upgrading embassy-net-nrf91; review its changelog for changed default buffer sizes

Example fix

// before
let mut mem = [0u8; 4096];
let allocator = Allocator::new(&mut mem);
// after
let mut mem = [0u8; 16384]; // fits buffers requested by config
let allocator = Allocator::new(&mut mem);
Defensive patterns

Strategy: validation

Validate before calling

fn validate_pool(mem_len: usize, buffers: usize, buffer_size: usize) {
    let required = buffers * buffer_size;
    assert!(mem_len >= required, "pool {} < required {}", mem_len, required);
}

Try / catch

// panic-based; validate sizes at startup instead
// assert!(mem.len() >= expected_total, "nrf91 memory pool too small");

Prevention

When it happens

Trigger: Calling the allocator path (e.g., constructing the Tcxo/AT or packet buffers) with size > available_size, i.e. the request exceeds the entire reserved memory region — typically on first allocation with an oversized configured buffer count/size.

Common situations: Configuring the driver with buffer sizes/counts that exceed the RAM budget set when creating the Allocator; upgrading the driver and its default packet size growing beyond a hand-tuned pool size; low-RAM targets (nrf9160 has limited RAM) where users shrink the pool too aggressively.

Understand the failure class

Background: "value must be between 0 and 1" / "out of range" / "must not be negative" errors: fixing range-validation failures across open-source libraries — this error's family across 42 libraries.

Related errors


AI-assisted analysis of embassy-rs/embassy@463a07b963 (2026-09-10). Data as JSON: /api/errors/888964f52b21f1c6. Report an issue: GitHub.

Appendix: source

Thrown at embassy-net-nrf91/src/lib.rs:60

pub fn on_ipc_irq() {
    trace!("irq");

    pac::IPC_NS.inten().write(|_| ());
    WAKER.wake();
}

struct Allocator<'a> {
    start: *mut u8,
    end: *mut u8,
    _phantom: PhantomData<&'a mut u8>,
}

impl<'a> Allocator<'a> {
    fn alloc_bytes(&mut self, size: usize) -> &'a mut [MaybeUninit<u8>] {
        // safety: both pointers come from the same allocation.
        let available_size = unsafe { self.end.offset_from(self.start) } as usize;
        if size > available_size {
            panic!("out of memory")
        }

        // safety: we've checked above this doesn't go out of bounds.
        let p = self.start;
        self.start = unsafe { p.add(size) };

        // safety: we've checked the pointer is in-bounds.
        unsafe { slice::from_raw_parts_mut(p as *mut _, size) }
    }

    fn alloc<T>(&mut self) -> &'a mut MaybeUninit<T> {
        let align = mem::align_of::<T>();
        let size = mem::size_of::<T>();

        let align_size = match (self.start as usize) % align {
            0 => 0,
            n => align - n,
        };

View on GitHub (pinned to 463a07b963)