rust-lang/rust · critical

Unexpected {} code: {:?}

Error message

Unexpected {} code: {:?}

What it means

Generated by the `fixed_size_enum!` macro in table.rs:89 inside `Option<T>::from_bytes`. rmeta stores fixed-size enums (e.g. Option<DefKind>, Option<CoroutineKind>, Option<MacroKind>) as single bytes where 0 = None and n = Some(variant n-1). A decoded byte that doesn't map to any known variant triggers this panic, proving the bytes are inconsistent with the decoder's enum definition.

Source

Thrown at compiler/rustc_metadata/src/rmeta/table.rs:89

    fn write_to_bytes(self, b: &mut [u8; 8]) {
        *b = self.to_le_bytes();
    }
}

macro_rules! fixed_size_enum {
    ($ty:ty { $(($($pat:tt)*))* } $( unreachable { $(($($upat:tt)*))+ } )?) => {
        impl FixedSizeEncoding for Option<$ty> {
            type ByteArray = [u8;1];

            #[inline]
            fn from_bytes(b: &[u8;1]) -> Self {
                use $ty::*;
                if b[0] == 0 {
                    return None;
                }
                match b[0] - 1 {
                    $(${index()} => Some($($pat)*),)*
                    _ => panic!("Unexpected {} code: {:?}", stringify!($ty), b[0]),
                }
            }

            #[inline]
            fn write_to_bytes(self, b: &mut [u8;1]) {
                use $ty::*;
                b[0] = match self {
                    None => unreachable!(),
                    $(Some($($pat)*) => 1 + ${index()},)*
                    $(Some($($($upat)*)|+) => unreachable!(),)?
                }
            }
        }
    }
}

macro_rules! defaulted_enum {
    ($ty:ty { $(($($pat:tt)*))* } $( unreachable { $(($($upat:tt)*))+ } )?) => {

View on GitHub (pinned to 22057b88b0)

Solutions

  1. Run `cargo clean` and rebuild the whole dependency tree with one consistent toolchain (`rustup show`, pin via `rust-toolchain.toml`).
  2. Delete stale incremental artifacts (`rm -rf target/debug/incremental` or the relevant profile dir) and rebuild.
  3. If it reproduces on a clean build with a single toolchain, capture a minimal repro and file a rustc issue — likely an encoder/decoder table out of sync.
Defensive patterns

Strategy: validation

Validate before calling

// Decode against an expected/known code range before handing the
// table to the consumer that would otherwise `unwrap`/`bug!`.
fn validate_table_code(kind: TableKind, code: u32) -> Result<(), String> {
    let max = kind.known_max_code();
    if code as usize <= max {
        Ok(())
    } else {
        Err(format!("unexpected {} code: {:?} (max known={})", kind, code, max))
    }
}

Type guard

fn is_known_table_code(kind: TableKind, code: u32) -> bool {
    kind.known_codes().contains(&code)
}

Try / catch

// Rust panics are not exceptions; isolate untrusted metadata decoding
// behind catch_unwind at a process/worker boundary.
let result = std::panic::catch_unwind(|| decode_rmeta_table(&bytes));
match result {
    Ok(table) => use_table(table),
    Err(payload) => report_corrupt_metadata(payload),
}

Prevention

When it happens

Trigger: Decoding an .rmeta/.rlib whose encoded enum discriminant has no match in the current compiler's variant list — produced by a rustc that added/removed/reordered enum variants, by a corrupted metadata blob, or by an internal encoder bug that wrote an out-of-range discriminant.

Common situations: Mixing artifacts compiled with different rustc versions (notably across nightlies that extend DefKind/CoroutineKind/MacroKind), pointing Cargo at a toolchain different from the one that built a dependency, or a stale incremental cache carrying incompatible metadata.

Related errors


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