rust-lang/rust · critical

dep node {prev_index:?} is unexpectedly red

Error message

dep node {prev_index:?} is unexpectedly red

What it means

ICE in Encoder::send_and_color (compiler/rustc_middle/src/dep_graph/serialized.rs:962). When re-encoding a node that existed in the previous graph, the code calls colors.try_set_color(prev_index, ...) and expects Success or AlreadyGreen; AlreadyRed is treated as a bug because the caller already decided this node is green (is_green == true) but the color map says it is red. It indicates an inconsistency between the marking pass and the encoding pass, often a race during parallel red-green marking.

Source

Thrown at compiler/rustc_middle/src/dep_graph/serialized.rs:962

        colors: &DepNodeColorMap,
        node: DepNode,
        value_fingerprint: Fingerprint,
        edges: &[DepNodeIndex],
        is_green: bool,
    ) -> DepNodeIndex {
        let _prof_timer = self.profiler.generic_activity("incr_comp_encode_dep_graph");
        let node = NodeInfo { node, value_fingerprint, edges };

        let mut local = self.status.local.borrow_mut();

        let index = self.status.next_index(&mut *local);
        let color = if is_green { DesiredColor::Green { index } } else { DesiredColor::Red };

        // Use `try_set_color` to avoid racing when `send_promoted` is called concurrently
        // on the same index.
        match colors.try_set_color(prev_index, color) {
            TrySetColorResult::Success => {}
            TrySetColorResult::AlreadyRed => panic!("dep node {prev_index:?} is unexpectedly red"),
            TrySetColorResult::AlreadyGreen { index } => return index,
        }

        self.status.bump_index(&mut *local);
        self.status.encode_node(index, &node, &self.retained_graph, &mut *local);
        index
    }

    /// Encodes a node that was promoted from the previous graph. It reads the information directly
    /// from the previous dep graph and expects all edges to already have a new dep node index
    /// assigned.
    ///
    /// Tries to mark the dep node green, and returns Some if it is now green,
    /// or None if had already been concurrently marked red.
    #[inline]
    pub(crate) fn send_promoted(
        &self,
        prev_index: SerializedDepNodeIndex,

View on GitHub (pinned to 22057b88b0)

Solutions

  1. Clear the incremental cache (target/**/incremental) and rebuild; the previous-session colors are the most likely source of the inconsistency.
  2. Run a clean build with -C incremental=no to confirm the ICE disappears without incremental compilation.
  3. If it reproduces on a clean build, report to the rustc team as a threading/race bug in DepNodeColorMap, including the prev_index from the message and the parallelism level.
Defensive patterns

Strategy: retry

Validate before calling

// "dep node is unexpectedly red" is an incremental consistency
// verification failure. No pre-call check exists; mitigate by
// detecting a stale/corrupt cache and clearing it.
fn cache_looks_stale(target: &std::path::Path) -> bool {
    let inc = target.join("incremental");
    // Heuristic: incremental dir exists but was touched before the
    // toolchain last changed.
    if let Ok(meta) = std::fs::metadata(&inc) {
        if let Ok(mtime) = meta.modified() {
            return mtime < toolchain_install_time();
        }
    }
    false
}

Try / catch

// Retry once after a cache wipe when this panic surfaces during
// incremental verification.
use std::panic::{catch_unwind, AssertUnwindSafe};

match catch_unwind(AssertUnwindSafe(|| compile_with_incremental(tcx))) {
    Ok(()) => {}
    Err(_) => {
        std::fs::remove_dir_all("target/debug/incremental").ok();
        compile_without_incremental(tcx);
    }
}

Prevention

When it happens

Trigger: try_set_color returns AlreadyRed while send_and_color was called with is_green=true. Typically happens under parallel query evaluation where two threads race to color the same SerializedDepNodeIndex and one marks it red (re-execute) while the other tries to mark it green (re-use).

Common situations: High-core / heavily parallel rustc builds stressing the red-green algorithm; races introduced by a refactor of DepNodeColorMap; corrupt previous-session colors loaded from a damaged incremental cache.

Related errors


AI-assisted analysis of rust-lang/rust@22057b88b0 (2026-08-03). Data as JSON: /data/errors/6338827037f6de60.json. Report an issue: GitHub.