atuinsh/atuin · critical
exceeded maximum allocation size
Error message
exceeded maximum allocation size
What it means
`Bucket::layout` builds the allocation layout for a bucket's entry array with `Layout::from_size_align(...).expect("exceeded maximum allocation size")`. It fails when `entry_size * bucket_len` exceeds `isize::MAX`, the largest allocation Rust permits. Bucket lengths double per bucket up to 2^31 entries, so this is reachable only near the tail of a multi-billion-entry vector, or with an oversized element type `T`.
Source
Thrown at crates/atuin-nucleo/src/boxcar.rs:495
vec: self.vec,
},
ParIterProducer {
start: self.start + index,
end: self.end,
vec: self.vec,
},
)
}
}
struct Bucket<T> {
entries: AtomicPtr<Entry<T>>,
}
impl<T> Bucket<T> {
fn layout(len: u32, layout: Layout) -> Layout {
Layout::from_size_align(layout.size() * len as usize, layout.align())
.expect("exceeded maximum allocation size")
}
unsafe fn alloc(len: u32, cols: u32) -> *mut Entry<T> {
let layout = Entry::<T>::layout(cols);
let arr_layout = Self::layout(len, layout);
let entries = std::alloc::alloc(arr_layout);
if entries.is_null() {
std::alloc::handle_alloc_error(arr_layout)
}
for i in 0..len {
let active = entries.add(i as usize * layout.size()) as *mut AtomicBool;
active.write(AtomicBool::new(false))
}
entries as *mut Entry<T>
}
unsafe fn dealloc(entries: *mut Entry<T>, len: u32, cols: u32) {View on GitHub (pinned to 15fe1318f1)
Solutions
- Keep the total item count far below the u32 boundary so late buckets are never allocated
- Pre-check intended sizes before pushing: `size_of::<T>() * planned_len <= isize::MAX as usize`
- Report upstream if hit with a plausible workload - capacity math should degrade gracefully, not abort
Example fix
// before vec.push(item, fill); // let bucket allocation fail late // after let planned = existing + 1; assert!(std::mem::size_of::<T>() as u64 * planned as u64 <= isize::MAX as u64); vec.push(item, fill);
Defensive patterns
Strategy: validation
Validate before calling
// Pre-check allocation math for your element type and scale
let per_entry = std::mem::size_of::<T>() as u64;
if per_entry.saturating_mul(planned_total) > isize::MAX as u64 {
return Err(AllocationTooLarge);
} Prevention
- Keep total item counts orders of magnitude below 2^32 so late (huge) buckets are never allocated
- Pre-compute worst-case entry sizes for custom T before injecting at scale
- Watch process memory growth - allocation failure here follows billions of successful pushes
When it happens
Trigger: Allocating the last buckets of a boxcar vector already holding ~4 billion items; a custom `T` so large that even moderate bucket lengths overflow `isize::MAX`.
Common situations: The same practically-unreachable territory as the u32 capacity panics: stress tests, fuzzing, or accidental re-push loops that inflate the vector to billions of rows.
Related errors
- overflowed maximum capacity
- exceeded maximum length
- creating threadpool failed
- issue in stats average query
- issue in stats exits query
AI-assisted analysis of atuinsh/atuin@15fe1318f1 (2026-08-19).
Data as JSON: /api/errors/7e3eb47830f6d608.
Report an issue: GitHub.