bevyengine/bevy · error · ScheduleError

SetNotFound

SetNotFound

Error message

Set not found

What it means

`ScheduleError::SetNotFound` is returned by `Schedule::systems_in_set` and the `remove_systems_in_set` family when the requested system set has no entry in that schedule — the set was never configured there and no system in that schedule references it via `.in_set`. Sets only exist in a schedule once something registers them in it.

Source

Thrown at crates/bevy_ecs/src/schedule/error.rs:289

        match self {
            ScheduleBuildWarning::HierarchyRedundancy(DagRedundancyError(transitive_edges)) => {
                ScheduleBuildError::hierarchy_redundancy_to_string(transitive_edges, graph)
            }
            ScheduleBuildWarning::Ambiguity(AmbiguousSystemConflictsWarning(ambiguities)) => {
                ScheduleBuildError::ambiguity_to_string(ambiguities, graph, world.components())
            }
        }
    }
}

/// Error returned from some `Schedule` methods
#[derive(Error, Debug)]
pub enum ScheduleError {
    /// Operation cannot be completed because the schedule has changed and `Schedule::initialize` needs to be called
    #[error("Operation cannot be completed because the schedule has changed and `Schedule::initialize` needs to be called")]
    Uninitialized,
    /// Method could not find set
    #[error("Set not found")]
    SetNotFound,
    /// Schedule not found
    #[error("Schedule not found.")]
    ScheduleNotFound,
    /// Error initializing schedule
    #[error("{0}")]
    ScheduleBuildError(ScheduleBuildError),
}

impl From<ScheduleBuildError> for ScheduleError {
    fn from(value: ScheduleBuildError) -> Self {
        Self::ScheduleBuildError(value)
    }
}

View on GitHub (pinned to 396ca72708)

Solutions

  1. Ensure the set exists in that schedule first: `.configure_sets(TheSchedule, MySet.run_if(...))` or add a system `.in_set(MySet)` there
  2. Verify you fetched the intended `ScheduleLabel` — set membership never carries across schedules
  3. Treat the `Err` as a legitimate 'empty' answer (Ok(0)/skip) in cleanup paths instead of unwrapping

Example fix

// before
let systems = schedule.systems_in_set(MySet).unwrap(); // Err(SetNotFound)

// after
app.configure_sets(Update, MySet); // ensure it exists in this schedule
let systems = schedule.systems_in_set(MySet)?;
Defensive patterns

Strategy: try-catch

Validate before calling

// Confirm the set is present in that schedule before querying
let known = schedule.systems_in_set(MySet).is_ok(); // after initialize
// or proactively ensure it exists:
app.configure_sets(Update, MySet);

Try / catch

match schedule.systems_in_set(MySet) {
    Err(ScheduleError::SetNotFound) => Ok(vec![]), // treat as empty set
    other => other.map(|s| s.iter().cloned().collect()),
}

Prevention

When it happens

Trigger: Calling `systems_in_set(MySet)` on a schedule where `MySet` was never configured (no `.configure_sets` call) and holds no systems; querying the right set on the wrong schedule label; removing systems from a set after the set was already removed with `RemoveSetAndSystems` policy.

Common situations: Assuming a plugin's set exists in every schedule; typos or using a similarly-named custom set instead of the intended one; querying before the plugin that populates the set has run; double-removal in cleanup code.

Related errors


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