bevyengine/bevy · error · MorphBuildError

Bevy only supports up to {} morph targets (individual poses)

Error message

Bevy only supports up to {} morph targets (individual poses), tried to create a model with {target_count} morph targets

What it means

MorphBuildError::TooManyTargets (crates/bevy_mesh/src/morph.rs:35) enforces MAX_MORPH_WEIGHTS = 256 morph targets per model. It is returned by MorphWeights::new when weights.len() > 256 and again by MorphTargetImage::new when targets.len() / vertex_count > 256. The weights are uploaded in a fixed-size buffer, so more poses cannot be represented.

Source

Thrown at crates/bevy_mesh/src/morph.rs:35

/// The maximum number of morph target components, if morph target textures are
/// in use on the current platform.
///
/// NOTE: "component" refers to the element count of math objects,
/// Vec3 has 3 components, Mat2 has 4 components.
const MAX_COMPONENTS: u32 = MAX_TEXTURE_WIDTH * MAX_TEXTURE_WIDTH;

#[derive(Error, Clone, Debug)]
pub enum MorphBuildError {
    #[error(
        "Too many vertex components in morph target, max is {MAX_COMPONENTS}, \
        got {vertex_count}×{component_count} = {}",
        *vertex_count * *component_count as usize
    )]
    TooManyAttributes {
        vertex_count: usize,
        component_count: u32,
    },
    #[error(
        "Bevy only supports up to {} morph targets (individual poses), tried to \
        create a model with {target_count} morph targets",
        MAX_MORPH_WEIGHTS
    )]
    TooManyTargets { target_count: usize },
}

/// Controls the [morph targets] for all child [`Mesh3d`](crate::Mesh3d)
/// entities. In most cases, [`MorphWeights`] should be considered the "source
/// of truth" when writing [morph targets] for meshes. However you can choose to
/// write child [`MeshMorphWeights`] if your situation requires more
/// granularity. Just note that if you set [`MorphWeights`], it will overwrite
/// child [`MeshMorphWeights`] values.
///
/// `MorphWeights` works together with the [`MeshMorphWeights`] component. When
/// a `MeshMorphWeights` is set to `MeshMorphWeights::Reference`, it references
/// another entity that is expected to contain a `MorphWeights` component. This
/// allows multiple meshes to share a single `MorphWeights` component.

View on GitHub (pinned to 396ca72708)

Solutions

  1. Prune the blendshape list in your DCC tool/exporter to at most 256 targets (delete unused or baked corrective shapes)
  2. Split the model so each mesh entity carries at most 256 of its own targets
  3. Bake rarely-used or always-together targets into fewer combined shapes before export

Example fix

// before
let weights = MorphWeights::new(all_300_shapes, Some(handle.clone())); // Err(TooManyTargets { target_count: 300 })

// after: prune to <= 256
let pruned: Vec<f32> = all_300_shapes.iter().copied().take(256).collect();
let weights = MorphWeights::new(pruned, Some(handle.clone())).unwrap();
Defensive patterns

Strategy: validation

Validate before calling

const MAX_TARGETS: usize = 256; // bevy_mesh::morph::MAX_MORPH_WEIGHTS

let weights: Vec<f32> = weights.into_iter().take(MAX_TARGETS).collect();
let morph = MorphWeights::new(weights, Some(handle.clone()))?;

Try / catch

if let Err(MorphBuildError::TooManyTargets { target_count }) =
    MorphWeights::new(weights, Some(handle.clone()))
{
    bevy::log::error!("{target_count} morph targets > 256; prune blendshapes");
}

Prevention

When it happens

Trigger: Constructing MorphWeights with a Vec<f32> longer than 256 entries, or loading a glTF whose mesh carries more than 256 morph targets (targets * vertex_count entries in the target array).

Common situations: DCC exports with hundreds of corrective blendshapes accumulated over production; scripts that generate one morph target per viseme/phoneme combination; combining several morph sets into one model without pruning.

Related errors


AI-assisted analysis of bevyengine/bevy@396ca72708 (2026-08-20). Data as JSON: /api/errors/137cf84de5f3afd2. Report an issue: GitHub.