gleam-lang/gleam · error

unknown pattern id

Error message

unknown pattern id

What it means

This is a Rust panic from an `expect` on a HashMap lookup in the Gleam compiler's exhaustiveness checker (`decision::reachability` pattern store). The compiler tried to fetch a Pattern by its arena Id, and the id was not present in the interner map. It is an internal invariant violation, not something pattern-matching user code did wrong semantically.

Solutions

  1. Ensure every `Id<Pattern>` you use was produced by the same `register`/pattern-store instance that is doing the lookup.
  2. Check for off-by-one or copied ids: regenerate the id via `register` instead of reusing a stale one.
  3. Replace `.expect` with a graceful error (Error::Bug / todo) if the id can legitimately be absent, and file a Gleam compiler bug with the crashing module if it is not your code.

Example fix

// before
let pattern = self.patterns.get_mut(pattern_id).expect("unknown pattern id");
// after
let pattern = self.patterns.get_mut(pattern_id).unwrap_or_else(|| {
    panic!("unknown pattern id {:?} in store of {} patterns", pattern_id, self.patterns.len())
});
Defensive patterns

Strategy: validation

Validate before calling

// Before relying on an Id<Pattern>, confirm it exists in the store:
assert!(store.patterns.contains_key(&pattern_id), "pattern id not registered in this store");

Type guard

fn is_registered(store: &PatternStore, id: Id<Pattern>) -> bool {
    store.patterns.contains_key(&id)
}

Try / catch

// Rust panics cannot be caught idiomaticly; catch at the binary boundary:
let result = std::panic::catch_unwind(|| compile_case(module));
match result { Ok(v) => v, Err(_) => report_bug("unknown pattern id") }

Prevention

When it happens

Trigger: Calling `DecisionReachability::pattern(pattern_id)` (directly or via `register`/check building) with an `Id<Pattern>` that was never inserted into `self.patterns`, or that came from a different pattern-store instance (e.g. ids created by another compilation of the same function).

Common situations: Developers hit this while hacking on the Gleam compiler itself: refactoring how patterns are registered, reusing pattern ids across two exhaustiveness runs, or building a `RuntimeCheckKind` from patterns that were never passed through `register`.

Understand the failure class

Background: "This is a bug, please report it": internal invariant violations, unreachable panics, and SNH errors explained — this error's family across 47 libraries.

Related errors


AI-assisted analysis of gleam-lang/gleam@49f8762da5 (2026-09-14). Data as JSON: /api/errors/d9b7320c68972b44. Report an issue: GitHub.

Appendix: source

Thrown at compiler-core/src/exhaustiveness.rs:2401

impl<'a> Compiler<'a> {
    fn new(environment: &'a Environment<'a>, variable_id: usize, patterns: Arena<Pattern>) -> Self {
        Self {
            environment,
            patterns,
            variable_id,
            diagnostics: Diagnostics {
                missing: false,
                reachable: HashSet::new(),
                match_impossible_variants: HashSet::new(),
                match_impossible_segments: HashMap::new(),
            },
        }
    }

    fn pattern(&mut self, pattern_id: Id<Pattern>) -> &mut Pattern {
        self.patterns
            .get_mut(pattern_id)
            .expect("unknown pattern id")
    }

    /// Returns a new fresh variable (i.e. guaranteed to have a unique `variable_id`)
    /// with the given type.
    ///
    fn fresh_variable(&mut self, type_: Arc<Type>) -> Variable {
        let var = Variable::new(self.variable_id, type_);
        self.variable_id += 1;
        var
    }

    fn mark_as_reached(&mut self, branch: &Branch) {
        let _ = self
            .diagnostics
            .reachable
            .insert((branch.clause_index, branch.alternative_index));
    }

View on GitHub (pinned to 49f8762da5)