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
- Increase the memory pool size passed when constructing the Allocator (and free up RAM elsewhere) so it can hold all configured buffers
- Reduce configured buffer count or MTU in the driver config so total required bytes fit the pool
- Compute the required pool size (buffers * buffer_size, plus allocator alignment) and size the static region accordingly
- 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
- Size the memory pool as buffers * buffer_size plus alignment headroom
- Recheck pool sizing after every driver version upgrade (defaults may change)
- Reduce buffer count/MTU when targeting low-RAM nrf9160 builds
- Log allocator usage at startup to confirm headroom before entering steady state
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
- Endpoint memory full
- Passphrase is too short or too long
- Boot prepare error
- Boot prepare error
- Boot prepare error
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)