bevyengine/bevy · error · WriteBufferRangeError
BufferNotInitialized
BufferNotInitialized
Error message
the gpu buffer is not initialized
What it means
WriteBufferRangeError::BufferNotInitialized is returned when write_buffer_range is called while the underlying wgpu buffer is None (buffer_vec.rs:212-213): the GPU buffer was never created because neither write_buffer() nor reserve() has run yet. Partial-range writes can only be queued onto an existing buffer.
Source
Thrown at crates/bevy_render/src/render_resource/buffer_vec.rs:982
T: NoUninit + Default,
{
/// Pushes `count` copies of `T::default` to the array.
pub fn push_multiple_init(&mut self, count: usize) -> usize {
debug_assert_eq!(self.uninit_element_count, 0);
let index = self.values.len();
self.values.extend(iter::repeat_n(T::default(), count));
index
}
}
/// Error returned when `write_buffer_range` fails
///
/// See [`RawBufferVec::write_buffer_range`] [`BufferVec::write_buffer_range`]
#[derive(Debug, Eq, PartialEq, Copy, Clone, Error)]
pub enum WriteBufferRangeError {
#[error("the range is bigger than the capacity of the buffer")]
RangeBiggerThanBuffer,
#[error("the gpu buffer is not initialized")]
BufferNotInitialized,
#[error("there are no values to upload")]
NoValuesToUpload,
}
#[inline]
#[cfg_attr(
not(feature = "type_label_buffers"),
expect(
clippy::extra_unused_type_parameters,
reason = "conditional compilation"
)
)]
pub(crate) fn make_buffer_label<'a, T>(label: &'a Option<String>) -> Option<&'a str> {
#[cfg(feature = "type_label_buffers")]
if label.is_none() {
return Some(core::any::type_name::<T>());
}View on GitHub (pinned to 396ca72708)
Solutions
- Initialize first: call vec.write_buffer(render_device, render_queue) once (creates and fills the buffer), or reserve(n, render_device).
- Order systems so the buffer-creating write happens before any partial-range updates (add explicit system ordering).
- Match on the error and initialize on demand before retrying.
Example fix
// before
let mut vec = RawBufferVec::default();
vec.push(value);
vec.write_buffer_range(queue, 0..1)?; // Err: buffer is None
// after
if vec.buffer().is_none() {
vec.write_buffer(render_device, queue); // creates the GPU buffer
}
vec.write_buffer_range(queue, 0..1)?; Defensive patterns
Strategy: validation
Validate before calling
if vec.buffer().is_none() {
vec.write_buffer(render_device, render_queue); // create the GPU buffer first
}
vec.write_buffer_range(queue, 0..vec.len())?; Try / catch
match vec.write_buffer_range(queue, 0..vec.len()) {
Err(WriteBufferRangeError::BufferNotInitialized) => {
vec.write_buffer(render_device, render_queue); // init, then retry
vec.write_buffer_range(queue, 0..vec.len())?
}
other => other?,
} Prevention
- Call write_buffer() or reserve() once when the BufferVec is created or first populated.
- Order buffer-creation systems before partial-update systems with explicit ordering constraints.
- Treat a None buffer as 'not yet on the GPU', not as an empty one.
When it happens
Trigger: Constructing a fresh BufferVec/RawBufferVec, pushing values, and calling write_buffer_range before any write_buffer(render_device, queue) or reserve(n, render_device) call created the GPU buffer.
Common situations: New render features with lazily-populated buffers; system ordering where a partial-update system runs before the buffer-creating system; buffers reused across frames but cleared in a way that drops the GPU buffer.
Related errors
- RangeBiggerThanBuffer
- NoValuesToUpload
- Uninitialized
- Error when initializing schedule {:?}: {}
- executable schedule has not been built
AI-assisted analysis of bevyengine/bevy@396ca72708 (2026-08-20).
Data as JSON: /api/errors/f33647e9f85fac57.
Report an issue: GitHub.