bevyengine/bevy · error

Binning main entity {:?} when it was already binned. This sh

Error message

Binning main entity {:?} when it was already binned. This should never happen.

What it means

This panic fires in RenderMultidrawableBin::insert when the entity_to_binned_mesh_instance_index map already contained an entry for the given MainEntity before the insert. That map is the authoritative record of which GPU instance slot an entity occupies; each entity must appear in exactly one bin, and moving an entity between bins requires an explicit remove first. Hitting this panic means a binning/rebinning code path (e.g. view or phase assignment logic) inserted the same entity twice without removing its prior entry, which would otherwise corrupt instance counts and leave a stale GPU instance slot. The input at fault is the duplicated MainEntity argument.

Source

Thrown at crates/bevy_render/src/render_phase/mod.rs:296

        // Create a `GpuRenderBinnedMeshInstance`.
        let gpu_render_bin_entry = GpuRenderBinnedMeshInstance {
            input_uniform_index: input_uniform_index.0,
            bin_index: bin_index.0,
        };

        // Allocate a spot for this entity in the `render_mesh_instance_buffer`.
        let render_binned_mesh_instance_buffer_index = RenderBinnedMeshInstanceIndex(
            self.render_binned_mesh_instance_buffer
                .push(GpuRenderBinnedMeshInstance::default()) as u32,
        );
        let maybe_previous_binned_mesh_instance_buffer_index = bin
            .entity_to_binned_mesh_instance_index
            .insert(main_entity, render_binned_mesh_instance_buffer_index);
        // It's illegal to bin an entity that was already binned.
        // If an entity is to change bins, it must first be removed from the bin
        // it was previously in.
        if maybe_previous_binned_mesh_instance_buffer_index.is_some() {
            panic!(
                "Binning main entity {:?} when it was already binned. This should never happen.",
                main_entity
            );
        }

        // Place the entry in the instance buffer at the proper spot.
        self.render_binned_mesh_instance_buffer.values_mut()
            [render_binned_mesh_instance_buffer_index.0 as usize] = gpu_render_bin_entry;

        let bin_metadata_index =
            self.bin_index_to_bin_metadata_index_buffer.values()[bin_index.0 as usize];
        // There should never be a previous binned mesh buffer index, because
        // it's illegal to bin a mesh instance that was already binned. But, if
        // that error case *does* happen due to a bug, then at least don't
        // corrupt the bins.
        if maybe_previous_binned_mesh_instance_buffer_index.is_none() {
            self.bin_metadata_buffer.values_mut()[bin_metadata_index as usize].instance_count += 1;
        }

View on GitHub (pinned to 221e52ae32)

Solutions

  1. Ensure the entity is removed from its previous bin (via the remove/swap_remove path) before inserting it into a new bin.
  2. Check the caller's binning loop for re-processing the same MainEntity in one frame (duplicate phase entries or missing per-frame reset of entity_to_binned_mesh_instance_index).
  3. If rebinning is intended, replace the plain insert with logic that detects the old index, decrements the old bin's instance_count, and frees the stale GPU slot instead of panicking.
Defensive patterns

Strategy: validation

When it happens

Trigger: Thrown at crates/bevy_render/src/render_phase/mod.rs:296 when the library encounters an invalid state.

Common situations: See trigger scenarios.


AI-assisted analysis of bevyengine/bevy@221e52ae32 (2026-09-05). Data as JSON: /api/errors/a987edea783d0ca6. Report an issue: GitHub.