bevyengine/bevy · critical
array layout should be valid
Error message
array layout should be valid
What it means
BlobArray::alloc computes the allocation layout as item_layout.repeat_packed(capacity) and expects it to be valid. Layout::repeat_packed only fails when capacity * item_size overflows the address space (result must stay within usize/isize bounds), so this panic means the requested element count times the item size is unrepresentable - a corrupted or astronomically large capacity, not a normal out-of-memory.
Source
Thrown at crates/bevy_ecs/src/storage/blob_array.rs:264
let item = self.get_unchecked_mut(last_element_index).promote();
// SAFETY:
unsafe { drop(item) };
self.drop = Some(drop);
}
}
/// Allocate a block of memory for the array. This should be used to initialize the array, do not use this
/// method if there are already elements stored in the array - use [`Self::realloc`] instead.
///
/// # Panics
/// - Panics if the new capacity overflows `isize::MAX` bytes.
/// - Panics if the allocation causes an out-of-memory error.
pub(super) fn alloc(&mut self, capacity: NonZeroUsize) {
#[cfg(debug_assertions)]
debug_assert_eq!(self.capacity, 0);
if !self.is_zst() {
let new_layout = self.item_layout.repeat_packed(capacity.get());
let new_layout = new_layout.expect("array layout should be valid");
// SAFETY: layout has non-zero size because capacity > 0, and the blob isn't ZST (`self.is_zst` == false)
let new_data = unsafe { alloc::alloc::alloc(new_layout) };
self.data = NonNull::new(new_data).unwrap_or_else(|| handle_alloc_error(new_layout));
}
#[cfg(debug_assertions)]
{
self.capacity = capacity.into();
}
}
/// Reallocate memory for this array.
/// For example, if the length (number of stored elements) reached the capacity (number of elements the current allocation can store),
/// you might want to use this method to increase the allocation, so more data can be stored in the array.
///
/// # Panics
/// - Panics if the new capacity overflows `isize::MAX` bytes.
/// - Panics if the allocation causes an out-of-memory error.
///View on GitHub (pinned to 396ca72708)
Solutions
- Trace where the capacity value comes from and fix the size computation - the panic means bytes = capacity x item_size overflowed.
- Validate/sanitize any size read from files/network (bounds caps, checked_mul) before it drives storage sizing.
- If the allocation is legitimately huge, batch it into smaller chunks or shrink the component layout.
Defensive patterns
Strategy: validation
Validate before calling
fn capacity_is_representable(item_layout: Layout, capacity: usize) -> bool {
item_layout.repeat_packed(capacity).is_ok()
} Prevention
- Use checked arithmetic (checked_mul/checked_add) when computing capacities from external data.
- Cap deserialized length/count fields at sane maxima before driving storage.
- Read this panic as a size-computation bug, not an OOM: inspect the capacity in a debugger.
When it happens
Trigger: A capacity value computed from untrusted or serialized input (entity counts, table sizing) that overflows before reaching alloc; arithmetic bugs producing near-usize::MAX element counts; huge component sizes multiplied by large capacities.
Common situations: Deserializing untrusted length prefixes; capacity math using wrapping/underflowed intermediates; 32-bit targets where the address space is exhausted by modest counts of large components.
Related errors
- Cannot call `ReflectComponent::reflect_mut` on component {na
- Cannot call `ReflectComponent::reflect_unchecked_mut` on com
- Resource entity {} of {} has been despawned, when it's not s
- System with key {:?} does not exist in the schedule
- System set with key {:?} does not exist in the schedule
AI-assisted analysis of bevyengine/bevy@396ca72708 (2026-08-20).
Data as JSON: /api/errors/b338102b7f8f133a.
Report an issue: GitHub.