Skip to content

Despawning observers through its target after despawning through another Relationship logs a warning! #24700

Description

@andriyDev

Bevy version and features

  • Bevy 0.18.1 and Bevy 0.19.0

What you did

I have observers that should despawn when either the target or the "owner" is despawned. So I used a linked_spawn RelationshipTarget so that the owner would delete the observer when the owner despawns.

use bevy::prelude::*;

fn main() {
    App::new()
        .add_plugins(DefaultPlugins)
        .add_systems(Startup, (setup, delete).chain())
        .add_observer(on_oo)
        .add_observer(on_wda)
        .add_observer(on_phs)
        .run();
}

fn setup(mut commands: Commands) {
    let target = commands.spawn(PlayerHandSlot).id();

    let owner = commands.spawn((WeaponDamageArea, ChildOf(target))).id();

    commands.spawn((
        Observer::new(|_: On<E>| {}).with_entity(target),
        ObserverOwner(owner),
    ));
}

fn delete(query: Query<Entity, With<PlayerHandSlot>>, mut commands: Commands) {
    for e in query.iter() {
        commands.entity(e).try_despawn();
    }
}

fn on_phs(_: On<Remove, PlayerHandSlot>) {
    dbg!("phs");
}

fn on_wda(_: On<Remove, WeaponDamageArea>) {
    dbg!("wda");
}

fn on_oo(_: On<Remove, ObserverOwner>) {
    dbg!("oo");
}

#[derive(EntityEvent)]
struct E(Entity);

#[derive(Component)]
struct WeaponDamageArea;

#[derive(Component)]
struct PlayerHandSlot;

#[derive(Component)]
#[relationship_target(relationship=ObserverOwner, linked_spawn)]
struct LinkedObservers(Vec<Entity>);

#[derive(Component)]
#[relationship(relationship_target=LinkedObservers)]
struct ObserverOwner(Entity);

What went wrong

The logs show the following message:

[src\main.rs:31:5] "phs" = "phs"
[src\main.rs:35:5] "wda" = "wda"
[src\main.rs:39:5] "oo" = "oo"
2026-06-22T03:29:36.608449Z  WARN bevy_ecs::error::handler: Encountered an error in command `<bevy_ecs::system::commands::entity_command::despawn::{{closure}} as bevy_ecs::system::commands::entity_command::EntityCommand>::with_entity::{{closure}}`: Entity despawned: The entity with ID 376v0 is invalid; its index now has generation 1.
Note that interacting with a despawned entity is the most common cause of this error but there are others

    If you were attempting to apply a command to this entity,
    and want to handle this error gracefully, consider using `EntityCommands::queue_handled` or `queue_silenced`.

Additional information

This only works depending on the observer ordering. Changing the names of the components above causes a different ordering, that doesn't have this warning. It seems to be when we've despawned an observer (through the linked_spawn thing), then the observer despawn tries to run and it fails. Or maybe it's the ObservedBy relationship target that is failing?

Metadata

Metadata

Assignees

No one assigned

    Labels

    A-ECSEntities, components, systems, and eventsC-BugAn unexpected or incorrect behaviorD-StraightforwardSimple bug fixes and API improvements, docs, test and examplesS-Needs-InvestigationThis issue requires detective work to figure out what's going wrong

    Type

    No type
    No fields configured for issues without a type.

    Projects

    Status
    Needs SME Triage

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions