bevyengine/bevy · warning · ScheduleBuildWarning

HierarchyRedundancy

HierarchyRedundancy

Error message

The hierarchy of system sets contains redundant edges: {0:?}

What it means

`HierarchyRedundancy` is a build warning (enabled by default) that the set-hierarchy graph contains edges already implied by transitive containment — e.g. C in B, B in A, plus an explicit C in A. The extra edge is not wrong, just redundant; it is reported because redundant edges usually indicate unintended hierarchy structure. It can be silenced via `ScheduleBuildSettings::hierarchy_detection = LogLevel::Ignore` or escalated to an error with `LogLevel::Error`.

Source

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

    /// A warning that was elevated to an error.
    #[error(transparent)]
    Elevated(#[from] ScheduleBuildWarning),
}

/// Category of warnings encountered during [`Schedule::initialize`](crate::schedule::Schedule::initialize).
#[non_exhaustive]
#[derive(Error, Debug)]
pub enum ScheduleBuildWarning {
    /// The hierarchy of system sets contains redundant edges.
    ///
    /// This warning is **enabled** by default, but can be disabled by setting
    /// [`ScheduleBuildSettings::hierarchy_detection`] to [`LogLevel::Ignore`]
    /// or upgraded to a [`ScheduleBuildError`] by setting it to [`LogLevel::Error`].
    ///
    /// [`ScheduleBuildSettings::hierarchy_detection`]: crate::schedule::ScheduleBuildSettings::hierarchy_detection
    /// [`LogLevel::Ignore`]: crate::schedule::LogLevel::Ignore
    /// [`LogLevel::Error`]: crate::schedule::LogLevel::Error
    #[error("The hierarchy of system sets contains redundant edges: {0:?}")]
    HierarchyRedundancy(#[from] DagRedundancyError<NodeId>),
    /// Systems with conflicting access have indeterminate run order.
    ///
    /// This warning is **disabled** by default, but can be enabled by setting
    /// [`ScheduleBuildSettings::ambiguity_detection`] to [`LogLevel::Warn`]
    /// or upgraded to a [`ScheduleBuildError`] by setting it to [`LogLevel::Error`].
    ///
    /// [`ScheduleBuildSettings::ambiguity_detection`]: crate::schedule::ScheduleBuildSettings::ambiguity_detection
    /// [`LogLevel::Warn`]: crate::schedule::LogLevel::Warn
    /// [`LogLevel::Error`]: crate::schedule::LogLevel::Error
    #[error(transparent)]
    Ambiguity(#[from] AmbiguousSystemConflictsWarning),
}

impl ScheduleBuildError {
    /// Renders the error as a human-readable string with node identifiers
    /// replaced with their names.
    ///

View on GitHub (pinned to 396ca72708)

Solutions

  1. Delete the implied edge (keep only `C.in_set(B)` in the example) so each nesting is declared once
  2. Centralize set-hierarchy declaration in the plugin that owns the sets instead of repeating edges across plugins
  3. If the redundancy is intentional, set `hierarchy_detection: LogLevel::Ignore` in that schedule's build settings to silence the warning

Example fix

// before
app.configure_sets(Update, (A, B.in_set(A), C.in_set(B).in_set(A))); // warning: C->A redundant

// after
app.configure_sets(Update, (A, B.in_set(A), C.in_set(B)));
Defensive patterns

Strategy: fallback

Validate before calling

// Before running, configure tolerance for known-redundant hierarchies
let mut schedule = schedules.get_mut(Update).unwrap();
let mut settings = schedule.get_build_settings().clone();
settings.hierarchy_detection = LogLevel::Ignore;
schedule.set_build_settings(settings);

Try / catch

// Warnings are logged during initialize; to fail closed instead, escalate:
settings.hierarchy_detection = LogLevel::Error; // HierarchyRedundancy becomes ScheduleBuildError
match schedule.initialize(&mut world) {
    Err(ScheduleBuildError::Elevated(w)) => { /* inspect warning, fix edges */ }
    _ => {}
}

Prevention

When it happens

Trigger: `.configure_sets(Update, (A, B.in_set(A), C.in_set(B).in_set(A)))` — the C→A edge is redundant; two plugins both nesting a shared set into the same ancestor.

Common situations: Plugin ecosystems where several plugins configure nesting into a common base set; refactors that add a direct `in_set` shortcut while the transitive path remains; merging example code that re-declares existing hierarchy edges.

Related errors


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