Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

System param validation error message for Option<Single<&Thing>> when there are two Things is confusing #17740

Open
scvalex opened this issue Feb 8, 2025 · 7 comments
Labels
C-Bug An unexpected or incorrect behavior S-Needs-Triage This issue needs to be labelled

Comments

@scvalex
Copy link
Contributor

scvalex commented Feb 8, 2025

Bevy version

0.15.2

What you did

The system param validation error message for Option<Single<&Thing>> when there are two Things is confusing.

use bevy::prelude::*;

#[derive(Component)]
struct Thing;

fn main() {
    App::new()
        .add_plugins(DefaultPlugins)
        .add_systems(Startup, setup)
        .add_systems(Update, update)
        .run();
}

fn setup(mut commands: Commands) {
    commands.spawn(Thing);
    commands.spawn(Thing);
}

fn update(_q: Option<Single<&Thing>>) {
    // meh
}

Running this gives the following error message: single_option_debug::update could not access system parameter Option<Single<Thing>>.

This confused me for a while because it seems to say that the Option<Single<&Thing>> isn't present, but the whole point of the option is for the system to work even if the Thing isn't there. I know it's obvious what's going on in this small example, but I encountered it in a bigger program where it was harder to figure out.

Full stdout:

thread 'main' panicked at /home/scvalex/.cargo/registry/src/index.crates.io-6f17d22bba15001f/bevy_ecs-0.15.2/src/system/function_system.rs:216:28:
single_option_debug::update could not access system parameter Option<Single<Thing>>
stack backtrace:
   0: rust_begin_unwind
             at /rustc/e71f9a9a98b0faf423844bf0ba7438f29dc27d58/library/std/src/panicking.rs:665:5
   1: core::panicking::panic_fmt
             at /rustc/e71f9a9a98b0faf423844bf0ba7438f29dc27d58/library/core/src/panicking.rs:76:14
   2: bevy_ecs::system::function_system::ParamWarnPolicy::try_warn
             at /home/scvalex/.cargo/registry/src/index.crates.io-6f17d22bba15001f/bevy_ecs-0.15.2/src/system/function_system.rs:216:28
   3: bevy_ecs::system::function_system::SystemMeta::try_warn_param
             at /home/scvalex/.cargo/registry/src/index.crates.io-6f17d22bba15001f/bevy_ecs-0.15.2/src/system/function_system.rs:137:9
   4: <core::option::Option<bevy_ecs::system::query::Single<D,F>> as bevy_ecs::system::system_param::SystemParam>::validate_param
             at /home/scvalex/.cargo/registry/src/index.crates.io-6f17d22bba15001f/bevy_ecs-0.15.2/src/system/system_param.rs:481:13
   5: <(P,) as bevy_ecs::system::system_param::SystemParam>::validate_param
             at /home/scvalex/.cargo/registry/src/index.crates.io-6f17d22bba15001f/bevy_ecs-0.15.2/src/system/system_param.rs:1940:19
   6: <bevy_ecs::system::function_system::FunctionSystem<Marker,F> as bevy_ecs::system::system::System>::validate_param_unsafe
             at /home/scvalex/.cargo/registry/src/index.crates.io-6f17d22bba15001f/bevy_ecs-0.15.2/src/system/function_system.rs:825:33
   7: bevy_ecs::schedule::executor::multi_threaded::ExecutorState::should_run
             at /home/scvalex/.cargo/registry/src/index.crates.io-6f17d22bba15001f/bevy_ecs-0.15.2/src/schedule/executor/multi_threaded.rs:575:41
   8: bevy_ecs::schedule::executor::multi_threaded::ExecutorState::spawn_system_tasks
             at /home/scvalex/.cargo/registry/src/index.crates.io-6f17d22bba15001f/bevy_ecs-0.15.2/src/schedule/executor/multi_threaded.rs:419:22
   9: bevy_ecs::schedule::executor::multi_threaded::ExecutorState::tick
             at /home/scvalex/.cargo/registry/src/index.crates.io-6f17d22bba15001f/bevy_ecs-0.15.2/src/schedule/executor/multi_threaded.rs:369:13
  10: bevy_ecs::schedule::executor::multi_threaded::Context::tick_executor
             at /home/scvalex/.cargo/registry/src/index.crates.io-6f17d22bba15001f/bevy_ecs-0.15.2/src/schedule/executor/multi_threaded.rs:309:13
  11: <bevy_ecs::schedule::executor::multi_threaded::MultiThreadedExecutor as bevy_ecs::schedule::executor::SystemExecutor>::run::{{closure}}
             at /home/scvalex/.cargo/registry/src/index.crates.io-6f17d22bba15001f/bevy_ecs-0.15.2/src/schedule/executor/multi_threaded.rs:229:17
  12: bevy_tasks::task_pool::TaskPool::scope_with_executor_inner
             at /home/scvalex/.cargo/registry/src/index.crates.io-6f17d22bba15001f/bevy_tasks-0.15.2/src/task_pool.rs:376:9
  13: bevy_tasks::task_pool::TaskPool::scope_with_executor::{{closure}}
             at /home/scvalex/.cargo/registry/src/index.crates.io-6f17d22bba15001f/bevy_tasks-0.15.2/src/task_pool.rs:311:17
  14: std::thread::local::LocalKey<T>::try_with
             at /nix/store/3zgclrg3234psfr5w56z0qfc954lb1hs-rust-default-1.84.1/lib/rustlib/src/rust/library/std/src/thread/local.rs:283:12
  15: std::thread::local::LocalKey<T>::with
             at /nix/store/3zgclrg3234psfr5w56z0qfc954lb1hs-rust-default-1.84.1/lib/rustlib/src/rust/library/std/src/thread/local.rs:260:9
  16: bevy_tasks::task_pool::TaskPool::scope_with_executor
             at /home/scvalex/.cargo/registry/src/index.crates.io-6f17d22bba15001f/bevy_tasks-0.15.2/src/task_pool.rs:307:9
  17: <bevy_ecs::schedule::executor::multi_threaded::MultiThreadedExecutor as bevy_ecs::schedule::executor::SystemExecutor>::run
             at /home/scvalex/.cargo/registry/src/index.crates.io-6f17d22bba15001f/bevy_ecs-0.15.2/src/schedule/executor/multi_threaded.rs:221:9
  18: bevy_ecs::schedule::schedule::Schedule::run
             at /home/scvalex/.cargo/registry/src/index.crates.io-6f17d22bba15001f/bevy_ecs-0.15.2/src/schedule/schedule.rs:386:9
  19: bevy_ecs::world::World::try_run_schedule::{{closure}}
             at /home/scvalex/.cargo/registry/src/index.crates.io-6f17d22bba15001f/bevy_ecs-0.15.2/src/world/mod.rs:3720:55
  20: bevy_ecs::world::World::try_schedule_scope
             at /home/scvalex/.cargo/registry/src/index.crates.io-6f17d22bba15001f/bevy_ecs-0.15.2/src/world/mod.rs:3653:21
  21: bevy_ecs::world::World::try_run_schedule
             at /home/scvalex/.cargo/registry/src/index.crates.io-6f17d22bba15001f/bevy_ecs-0.15.2/src/world/mod.rs:3720:9
  22: bevy_app::main_schedule::Main::run_main::{{closure}}
             at /home/scvalex/.cargo/registry/src/index.crates.io-6f17d22bba15001f/bevy_app-0.15.2/src/main_schedule.rs:279:25
  23: bevy_ecs::world::World::resource_scope
             at /home/scvalex/.cargo/registry/src/index.crates.io-6f17d22bba15001f/bevy_ecs-0.15.2/src/world/mod.rs:2824:22
  24: bevy_app::main_schedule::Main::run_main
             at /home/scvalex/.cargo/registry/src/index.crates.io-6f17d22bba15001f/bevy_app-0.15.2/src/main_schedule.rs:277:9
  25: core::ops::function::FnMut::call_mut
             at /nix/store/3zgclrg3234psfr5w56z0qfc954lb1hs-rust-default-1.84.1/lib/rustlib/src/rust/library/core/src/ops/function.rs:166:5
  26: core::ops::function::impls::<impl core::ops::function::FnMut<A> for &mut F>::call_mut
             at /nix/store/3zgclrg3234psfr5w56z0qfc954lb1hs-rust-default-1.84.1/lib/rustlib/src/rust/library/core/src/ops/function.rs:294:13
  27: <Func as bevy_ecs::system::exclusive_function_system::ExclusiveSystemParamFunction<fn(F0).> Out>>::run::call_inner
             at /home/scvalex/.cargo/registry/src/index.crates.io-6f17d22bba15001f/bevy_ecs-0.15.2/src/system/exclusive_function_system.rs:245:21
  28: <Func as bevy_ecs::system::exclusive_function_system::ExclusiveSystemParamFunction<fn(F0).> Out>>::run
             at /home/scvalex/.cargo/registry/src/index.crates.io-6f17d22bba15001f/bevy_ecs-0.15.2/src/system/exclusive_function_system.rs:248:17
  29: <bevy_ecs::system::exclusive_function_system::ExclusiveFunctionSystem<Marker,F> as bevy_ecs::system::system::System>::run::{{closure}}
             at /home/scvalex/.cargo/registry/src/index.crates.io-6f17d22bba15001f/bevy_ecs-0.15.2/src/system/exclusive_function_system.rs:129:23
  30: bevy_ecs::world::World::last_change_tick_scope
             at /home/scvalex/.cargo/registry/src/index.crates.io-6f17d22bba15001f/bevy_ecs-0.15.2/src/world/mod.rs:3187:9
  31: <bevy_ecs::system::exclusive_function_system::ExclusiveFunctionSystem<Marker,F> as bevy_ecs::system::system::System>::run
             at /home/scvalex/.cargo/registry/src/index.crates.io-6f17d22bba15001f/bevy_ecs-0.15.2/src/system/exclusive_function_system.rs:121:9
note: Some details are omitted, run with `RUST_BACKTRACE=full` for a verbose backtrace.
Encountered a panic in system `bevy_app::main_schedule::Main::run_main`!
@scvalex scvalex added C-Bug An unexpected or incorrect behavior S-Needs-Triage This issue needs to be labelled labels Feb 8, 2025
@homebrewmellow
Copy link

Single
"System parameter that provides access to single entity's components, much like Query::single/Query::single_mut.
This SystemParam fails validation if zero or more than one matching entity exists. This will cause a panic, but can be configured to do nothing or warn once.
Use [Option<Single<D, F>>] instead if zero or one matching entities can exist."

you can't use Single with 2 or more items

@homebrewmellow
Copy link

fn dostuff(entities: Query<Entity, With<MyComponent>>, mut commands: Commands) {
    for entity in &entities {
            commands.entity(entity) //.dosomething(.....)

    }
}

does this satisfy what you need to do?

@scvalex
Copy link
Contributor Author

scvalex commented Feb 9, 2025

My complaint is about the error message. It seems to be saying that there are zero things when the problem is in fact that there are multiple things.

@homebrewmellow
Copy link

Option works fine. there is a Single. the Single itself can't handle it's data.

I agree that the error message doesn't help. should say something like "Panic! Single has invalid data"

@simbleau
Copy link
Contributor

simbleau commented Feb 9, 2025

Totally agree with OP here,

  • Option<Single> should return None when there is 0 Things.
  • Option<Single> should return Some(Thing) when there is 1 Thing.
  • Option<Single> should return None when there is 2 or more Things.
    • Current behavior: Undocumented panic.

This needs to be fixed asap.

@scvalex
Copy link
Contributor Author

scvalex commented Feb 9, 2025

Option should return None when there is 2 or more Things.

I don't actually agree with that. I think it's fine for it to fail, but the error message should say that it's failing because there was more than one result to the query.

@scvalex
Copy link
Contributor Author

scvalex commented Feb 9, 2025

Let me clarify:

When a user writes Option<Single<Thing>>, they are clearly saying they expect zero or one of the thing. When there are multiple things, it's confusing that it fails saying could not access system parameter which is the same error you get when you try to query for a Single<Thing>, but forget to add it to the world.

That it fails at runtime is not great, but it's the documented behaviour of a Single<_>. I think it would be worse if instead of panicking, it silently returned nothing where there were multiple things—this would just be confusing.

However, I think the panic message should be improved so that it says what the problem actually is.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
C-Bug An unexpected or incorrect behavior S-Needs-Triage This issue needs to be labelled
Projects
None yet
Development

No branches or pull requests

3 participants