emilk/egui · error

You must call .update_buffers() before .render()

Error message

You must call .update_buffers() before .render()

What it means

In egui-wgpu's renderer, render() advances pre-built buffer slice iterators for each mesh. If the iterators are empty, render was called without a prior update_buffers() call, so the slices from the uploaded buffers don't match the painted primitives. The library panics because continuing would render garbage indices.

Source

Thrown at crates/egui-wgpu/src/renderer.rs:552

                    size_in_pixels[1] as f32,
                    0.0,
                    1.0,
                );
                render_pass.set_pipeline(&self.pipeline);
                render_pass.set_bind_group(0, &self.uniform_bind_group, &[]);
                needs_reset = false;
            }

            {
                let rect = ScissorRect::new(clip_rect, pixels_per_point, size_in_pixels);

                if rect.width == 0 || rect.height == 0 {
                    // Skip rendering zero-sized clip areas.
                    if let Primitive::Mesh(_) = primitive {
                        // If this is a mesh, we need to advance the index and vertex buffer iterators:
                        index_buffer_slices
                            .next()
                            .expect("You must call .update_buffers() before .render()");
                        vertex_buffer_slices
                            .next()
                            .expect("You must call .update_buffers() before .render()");
                    }
                    continue;
                }

                render_pass.set_scissor_rect(rect.x, rect.y, rect.width, rect.height);
            }

            match primitive {
                Primitive::Mesh(mesh) => {
                    let index_buffer_slice = index_buffer_slices
                        .next()
                        .expect("You must call .update_buffers() before .render()");
                    let vertex_buffer_slice = vertex_buffer_slices
                        .next()
                        .expect("You must call .update_buffers() before .render()");

View on GitHub (pinned to 441971a776)

Solutions

  1. Call renderer.update_buffers(device, queue, encoder, clipped_primitives, screen_descriptor) before render and pass the returned Vec<BufferDimensions> usage onward.
  2. Use the standard egui_wgpu::Renderer::render flow (it manages update_buffers internally) rather than a custom one.
  3. Update integration code copied from outdated examples to the current egui-wgpu render pattern.

Example fix

// before
renderer.render(&mut render_pass, &clipped_primitives, &screen);
// after
let buffer_slices = renderer.update_buffers(&device, &queue, &mut encoder, &clipped_primitives, &screen);
renderer.render(&mut render_pass, &clipped_primitives, &buffer_slices, &screen);
Defensive patterns

Strategy: validation

Validate before calling

// Ensure this ran in the same frame:
// let slices = renderer.update_buffers(&device, &queue, &mut encoder, &clipped_primitives, &screen_descriptor);

Type guard

fn slices_ready(slices: &[egui_wgpu::BufferDimensions], prims: &[ClippedPrimitive]) -> bool { !prims.iter().any(|p| matches!(p.primitive, Primitive::Mesh(_))) || !slices.is_empty() }

Try / catch

// Panic in release too; not catchable per-call. Prevent by structuring code so update_buffers always precedes render.

Prevention

When it happens

Trigger: Calling CallbackTrait::render (or egui_wgpu::Renderer::render) directly without calling renderer.update_buffers(...) first for the same screen descriptor and clipped primitives, in a custom integration or custom paint callback.

Common situations: Custom egui-wgpu integrations written before/without update_buffers (API added to fix multi-mesh rendering); users overriding render in a paint callback; porting older integration code to a newer egui-wgpu where render no longer does buffer uploads itself.

Understand the failure class

Background: "Invalid state transition" errors: "status must be X, actually Y", "already rejected/charging/uninstalled", "cannot ... while running" — what they mean when a library rejects your call — this error's family across 31 libraries.

Related errors


AI-assisted analysis of emilk/egui@441971a776 (2026-09-12). Data as JSON: /api/errors/506981f1f72cf9ff. Report an issue: GitHub.