bevyengine/bevy · error · TypeInfoError

kind mismatch: expected {expected:?}, received {received:?}

Error message

kind mismatch: expected {expected:?}, received {received:?}

What it means

TypeInfo describes a reflected type's shape (StructInfo, MapInfo, ListInfo, ...). The generated convenience casts TypeInfo::as_struct/as_tuple_struct/as_tuple/as_list/as_array/as_map/as_set/as_enum/as_opaque return Result<&XxxInfo, TypeInfoError>, and the error's KindMismatch variant reports expected vs received ReflectKind when the info is a different kind (e.g. calling as_struct on Vec<i32>, which is a List).

Source

Thrown at crates/bevy_reflect/src/info/error.rs:12

use crate::ReflectKind;
use thiserror::Error;

/// A [`TypeInfo`]-specific error.
///
/// [`TypeInfo`]: crate::info::TypeInfo
#[derive(Debug, Error)]
pub enum TypeInfoError {
    /// Caused when a type was expected to be of a certain [kind], but was not.
    ///
    /// [kind]: ReflectKind
    #[error("kind mismatch: expected {expected:?}, received {received:?}")]
    KindMismatch {
        /// Expected kind.
        expected: ReflectKind,
        /// Received kind.
        received: ReflectKind,
    },
}

View on GitHub (pinned to 396ca72708)

Solutions

  1. Match on info.kind() (or the TypeInfo enum itself) first and handle every arm instead of assuming one kind.
  2. Use the typed data when available: prefer ReflectRef (reflect_ref()) for value-level access, or store the expected kind next to the lookup.
  3. Handle the Err case of as_* with a fallback instead of unwrap/expect.
  4. If a specific kind was genuinely intended, fix the caller: the type being inspected is of the 'received' kind shown in the message.

Example fix

// before
let info = <Vec<i32> as Typed>::type_info();
let s = info.as_struct().unwrap(); // KindMismatch: expected Struct, received List

// after
match <Vec<i32> as Typed>::type_info() {
    TypeInfo::List(li) => println!("item: {:?}", li.type_item()),
    other => println!("unexpected kind: {:?}", other.kind()),
}
Defensive patterns

Strategy: try-catch

Validate before calling

let info = registration.type_info();
if info.kind() == ReflectKind::Map {
    let map_info = info.as_map().expect("kind checked above");
    // ...
}

Type guard

fn is_map_info(info: &TypeInfo) -> bool {
    info.kind() == ReflectKind::Map
}

Try / catch

match typed_type.type_info().as_map() {
    Ok(map_info) => { /* handle map info */ }
    Err(TypeInfoError::KindMismatch { expected, received }) => {
        warn!("expected {expected:?}, got {received:?}; skipping type");
    }
}

Prevention

When it happens

Trigger: Calling a TypeInfo::as_* cast whose target kind does not match the actual type: type_info().as_map() on a Vec, registration.type_info().as_struct() on an enum, etc.

Common situations: Registry/tooling code that iterates registered types and assumes a kind; serializers or inspectors switching on TypeInfo but forgetting variants; refactors that change a component from struct to enum or add generics that alter kind.

Related errors


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