Skip to content

BRP Issue: Components with only Reflect cannot be spawned/inserted #20952

@natepiano

Description

@natepiano

Bevy version and features

  • version: 0.16.1 but i believe the issue still persists
  • no features

What you did

using the bevy remote protocol, if i try to bevy/spawn or bevy/insert on a Component and do not derive Deserialize and reflect Deserialize it gets an error

here's the report i came up with

BRP Issue: Components with only Reflect cannot be spawned/inserted

The Problem

In Bevy 0.16.1, components that only derive Reflect (without Serialize/Deserialize) fail to spawn via BRP with the error:

Unknown component type: `bevy_reflect::DynamicStruct`

Root Cause Analysis

When process_remote_spawn_request receives a spawn request:

  1. deserialize_components creates a TypedReflectDeserializer and calls deserialize()

  2. The deserializer checks for:

    • ReflectDeserialize (requires #[derive(Deserialize)] + #[reflect(Deserialize)])
    • ReflectDeserializeWithRegistry (requires manual registration)
  3. Without these traits, it falls back to deserialize_struct() which creates a DynamicStruct - a generic container that knows it represents the actual type via set_represented_type()

  4. This DynamicStruct is passed to insert_reflected_components which calls:

    get_reflect_component(type_registry, reflected.reflect_type_path())
  5. The bug: reflect_type_path() on DynamicStruct returns "bevy_reflect::DynamicStruct" (from impl_type_path! macro) instead of the represented type's path

  6. get_reflect_component fails because "bevy_reflect::DynamicStruct" isn't registered as a component

The Fix

In insert_reflected_components, check for a represented type first:

fn insert_reflected_components(
    type_registry: &TypeRegistry,
    mut entity_world_mut: EntityWorldMut,
    reflect_components: Vec<Box<dyn PartialReflect>>,
) -> AnyhowResult<()> {
    for reflected in reflect_components {
        let type_path = if let Some(represented_type_info) = reflected.get_represented_type_info() {
            represented_type_info.type_path()  // Use the actual component type
        } else {
            reflected.reflect_type_path()      // Fallback for non-dynamic types
        };
        
        let reflect_component = get_reflect_component(type_registry, type_path)?;
        reflect_component.insert(&mut entity_world_mut, &*reflected, type_registry);
    }

    Ok(())
}

Verification

I've tested this fix on Bevy 0.16.1 and confirmed it works - components with only Reflect can now be successfully spawned and inserted via BRP.

Help requested

I'm not a bevy contributor and i don't know the rules - mostly i'm concerned while that this is just a few lines of code to fix in an existing function i want to make sure that it's the right few lines of code. Not being a bevy_remote or bevy_reflect developer I would love it if someone who was could look at this issue and fix it correctly.

It's a big issue for me and I would love it if it this could make it into 17 as a bug fix.

Metadata

Metadata

Assignees

No one assigned

    Labels

    A-Dev-ToolsTools used to debug Bevy applications.A-ReflectionRuntime information about typesC-BugAn unexpected or incorrect behaviorS-Ready-For-ImplementationThis issue is ready for an implementation PR. Go for it!

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions