{"record":{"id":"cec01aaa4d32161a","repo":"bevyengine/bevy","slug":"failed-to-get-buffer","errorCode":null,"errorMessage":"Failed to get buffer","messagePattern":"Failed to get buffer","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/bevy_render/src/render_resource/storage_buffer.rs","lineNumber":155,"sourceCode":"        if capacity < size || self.changed {\n            self.buffer = Some(device.create_buffer_with_data(&BufferInitDescriptor {\n                label: make_buffer_label::<Self>(&self.label),\n                usage: self.buffer_usage,\n                contents: self.scratch.as_ref(),\n            }));\n            self.changed = false;\n        } else if let Some(buffer) = &self.buffer {\n            queue.write_buffer(buffer, 0, self.scratch.as_ref());\n        }\n\n        self.last_written_size = BufferSize::new(size);\n    }\n}\n\nimpl<'a, T: ShaderType + WriteInto> IntoBinding<'a> for &'a StorageBuffer<T> {\n    #[inline]\n    fn into_binding(self) -> BindingResource<'a> {\n        self.binding().expect(\"Failed to get buffer\")\n    }\n}\n\n/// Stores data to be transferred to the GPU and made accessible to shaders as a dynamic storage buffer.\n///\n/// This is just a [`StorageBuffer`], but also allows you to set dynamic offsets.\n///\n/// Dynamic storage buffers can be made available to shaders in some combination of read/write mode, and can store large amounts\n/// of data. Note however that WebGL2 does not support storage buffers, so consider alternative options in this case. Dynamic\n/// storage buffers support multiple separate bindings at dynamic byte offsets and so have a\n/// [`push`](DynamicStorageBuffer::push) method.\n///\n/// The contained data is stored in system RAM. [`write_buffer`](DynamicStorageBuffer::write_buffer)\n/// queues copying of the data from system RAM to VRAM. The data within a storage buffer binding must conform to\n/// [std430 alignment/padding requirements]. `DynamicStorageBuffer` takes care of serializing the inner type to conform to\n/// these requirements. Each item [`push`](DynamicStorageBuffer::push)ed into this structure\n/// will additionally be aligned to meet dynamic offset alignment requirements.\n///","sourceCodeStart":137,"sourceCodeEnd":173,"githubUrl":"https://github.com/bevyengine/bevy/blob/396ca727080776bd313bb892423b7d94e03b81b4/crates/bevy_render/src/render_resource/storage_buffer.rs#L137-L173","documentation":"IntoBinding for &StorageBuffer<T> calls self.binding().expect(\"Failed to get buffer\"). binding() (storage_buffer.rs:82) returns None while the inner GPU Buffer has never been allocated — the buffer is only created inside write_buffer() on the first non-empty write. So converting the storage buffer into a BindingResource before the first write_buffer() call panics.","triggerScenarios":"Using &storage_buffer as a binding (e.g. BindGroupEntries::sequential_with_label(.., [&storage_buffer]) or entries.add(&storage_buffer)) in a system that runs before StorageBuffer::write_buffer(&queue) was ever called for that buffer.","commonSituations":"System-ordering mistakes where the bind-group-building system runs before the buffer-writing system each frame; forgetting to call write_buffer at all after set(); a newly added buffer that is bound on frame 0 before its first write.","solutions":["Call storage_buffer.write_buffer(&queue) in a system ordered before the one that builds the bind group (use .before()/ordering or system sets)","Make sure you set() data at least once — an empty scratch buffer has nothing to upload","Instead of relying on IntoBinding, use binding() directly and skip bind-group creation while it returns None"],"exampleFix":"// before\nfn build_bind_group(buffer: &StorageBuffer<MyData>, ...) {\n    let entries = BindGroupEntries::sequential([&buffer]); // panics if never written\n}\n\n// after\nfn write_buffer_system(buffer: &mut StorageBuffer<MyData>, queue: &RenderQueue) {\n    buffer.write_buffer(queue); // allocates the GPU buffer first\n}\nfn build_bind_group_system(buffer: &StorageBuffer<MyData>, ...) {\n    let entries = BindGroupEntries::sequential([&buffer]);\n}","handlingStrategy":"validation","validationCode":"// Before building the bind group:\nif storage_buffer.buffer().is_none() {\n    // write_buffer(&queue) has never run; skip this frame or write now\n    return;\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Call write_buffer(&queue) in a system strictly ordered before bind-group construction","Reach for binding() (Option) instead of the IntoBinding impl when the write may not have happened","Centralize 'upload then bind' in the same system when ordering control is difficult"],"tags":["bevy","storage-buffer","gpu-buffer","binding","panic"],"backgroundTag":"gpu-buffer-not-initialized","analyzedSha":"396ca727080776bd313bb892423b7d94e03b81b4","analyzedAt":"2026-08-20T16:12:39.808Z","contentChangedAt":"2026-08-20T16:12:39.808Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}