bevyengine/bevy · error · AccessFailed

Unsupported vertex attribute format

Error message

Unsupported vertex attribute format

What it means

AccessFailed::UnsupportedFormat fires from two sites in vertex_attributes.rs: the catch-all of VertexAttributeIter::from_accessor (line 135) when the accessor's (DataType, Dimensions) pair is not in the supported table — FLOAT16 data, matrix types, or exotic combos like I8 Vec3 — and BufferAccessor::with_no_norm (line 64) when a float/uint accessor is marked "normalized": true, which only makes sense for signed/unsigned ints and is rejected. It reaches callers as ConvertAttributeError::AccessFailed(UnsupportedFormat, accessor_index).

Source

Thrown at crates/bevy_gltf/src/vertex_attributes.rs:38

        unnormalized_ctor: impl Fn(T) -> U,
    ) -> U {
        if self.0 {
            normalized_ctor(value)
        } else {
            unnormalized_ctor(value)
        }
    }
}

/// An error that occurs when accessing buffer data
#[derive(Error, Debug)]
pub enum AccessFailed {
    /// Accessing the data failed because of an issue like a mismatch in stride,
    /// or a buffer view slice failing.
    #[error("Malformed vertex attribute data")]
    MalformedData,
    /// The format supplied is unsupported for this operation.
    #[error("Unsupported vertex attribute format")]
    UnsupportedFormat,
}

/// Helper for reading buffer data
struct BufferAccessor<'a> {
    accessor: gltf::Accessor<'a>,
    buffer_data: &'a Vec<Vec<u8>>,
    normalization: Normalization,
}

impl<'a> BufferAccessor<'a> {
    /// Creates an iterator over the elements in this accessor
    fn iter<T: gltf::accessor::Item>(self) -> Result<gltf::accessor::Iter<'a, T>, AccessFailed> {
        gltf::accessor::Iter::new(self.accessor, |buffer: gltf::Buffer| {
            self.buffer_data.get(buffer.index()).map(Vec::as_slice)
        })
        .ok_or(AccessFailed::MalformedData)
    }

View on GitHub (pinned to 396ca72708)

Solutions

  1. Re-export with float32 for standard attributes, or use one of the supported integer combos (U8/I8/U16/I16 in Vec2/Vec3/Vec4, U32/F32 in all dimensions).
  2. Remove 'normalized' flags from float accessors.
  3. If you need half-float or exotic layouts, convert to a supported layout in an offline step before loading.

Example fix

// accessor (before)
{ "componentType": 5123, "type": "VEC3", "normalized": true }  // U16 Vec3 unsupported combo
// (after)
{ "componentType": 5126, "type": "VEC3" }  // FLOAT Vec3, always supported
Defensive patterns

Strategy: validation

Validate before calling

fn accessor_format_supported(a: &gltf::Accessor) -> bool {
    use gltf::accessor::{DataType as D, Dimensions as V};
    let float_like = matches!(a.data_type(), D::F32 | D::U32);
    if a.normalized() && float_like { return false; } // with_no_norm rejects this
    matches!((a.data_type(), a.dimensions()),
        (D::F32, _) | (D::U32, _)
        | (D::I16, V::Vec2) | (D::U16, V::Vec2) | (D::I16, V::Vec4) | (D::U16, V::Vec4)
        | (D::I8, V::Vec2) | (D::U8, V::Vec2) | (D::I8, V::Vec4) | (D::U8, V::Vec4)
        | (D::U16, V::Vec3) | (D::U8, V::Vec3))
}

Type guard

fn is_supported_vertex_format(dt: gltf::accessor::DataType, dims: gltf::accessor::Dimensions) -> bool {
    use gltf::accessor::{DataType as D, Dimensions as V};
    matches!((dt, dims), (D::F32, _) | (D::U32, _) | (D::I16, V::Vec2) | (D::U16, V::Vec2)
        | (D::I16, V::Vec4) | (D::U16, V::Vec4) | (D::I8, V::Vec2) | (D::U8, V::Vec2)
        | (D::I8, V::Vec4) | (D::U8, V::Vec4) | (D::U16, V::Vec3) | (D::U8, V::Vec3))
}

Try / catch

match err {
    ConvertAttributeError::AccessFailed(AccessFailed::UnsupportedFormat, idx) => {
        error!("accessor {idx} uses an unsupported componentType/type (or normalized floats); re-export with supported formats");
    }
    other => return Err(other.into()),
}

Prevention

When it happens

Trigger: POSITION/TEXCOORD stored as VEC3/VEC2 of FLOAT16 (exporter 'half float' option); "normalized": true on a F32 accessor; MAT2/MAT3 attributes; I16 Vec3 colors.

Common situations: DCC precision settings ('Half Float'), KHR_mesh_quantization-style assets using unsupported component types/dimensions, custom attribute pipelines copying whatever the source mesh had.

Related errors


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