gleam-lang/gleam · error

unreachable

Error message

unreachable

What it means

Internal invariant panic in `runtime_check` for JavaScript code generation (compiler-core/src/javascript/decision.rs:1648). When generating a runtime check for a bit array segment, the matched value must be a literal-like variant that maps to a check (e.g. int/string); `Variable`, `Discard`, or `Assign` variants require no runtime check, and encountering them in the check-building position is unreachable by construction, so the compiler panics with `"unreachable"`.

Solutions

  1. Upgrade to the latest gleam compiler; this should be unreachable on supported releases.
  2. Work around by restructuring the case: bind aliased segments separately instead of inside the matched segment.
  3. File a bug with the failing pattern, target (JavaScript), and compiler version so the decision-tree builder can be fixed.
  4. Compiler contributors: assert/normalize `BitArrayMatchedValue` variants before constructing `RuntimeCheck`s.

Example fix

// before: alias inside the segment triggers the buggy path (compiler bug)
let <<a:size(8) as b>> = bits
// after: separate the binding
let <<a:size(8)>> = bits
let b = a
Defensive patterns

Strategy: type-guard

Validate before calling

// only build runtime checks for checkable matched values
if matches!(value, BitArrayMatchedValue::Variable(_) | BitArrayMatchedValue::Discard(_) | BitArrayMatchedValue::Assign { .. }) {
    return Ok(None); // no check needed
}

Type guard

fn needs_runtime_check(v: &BitArrayMatchedValue) -> bool {
    !matches!(v, BitArrayMatchedValue::Variable(_) | BitArrayMatchedValue::Discard(_) | BitArrayMatchedValue::Assign { .. })
}

Prevention

When it happens

Trigger: Compiling a JavaScript-target `case` on a bit array where the decision-tree builder hands an aliased/wildcard segment value into runtime check construction — only possible via a compiler bug in pattern binding classification or a patched build.

Common situations: Gleam compiler developers working on the JS backend's bit array case compilation; users of pre-release or forked compilers compiling bit array patterns with aliases/discards to JavaScript; not expected from valid code on stable releases.

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/c822f142a1af55bd. Report an issue: GitHub.

Appendix: source

Thrown at compiler-core/src/javascript/decision.rs:1648

                        bytes: expected,
                    } => {
                        self.literal_string_segment_bytes_check(arena, value, expected, read_action)
                    }
                    BitArrayMatchedValue::LiteralFloat(expected) => {
                        self.literal_float_segment_bytes_check(arena, value, expected, read_action)
                    }
                    BitArrayMatchedValue::LiteralInt {
                        value: expected, ..
                    } => self.literal_int_segment_bytes_check(
                        arena,
                        value,
                        expected.clone(),
                        read_action,
                    ),
                    BitArrayMatchedValue::Variable(..)
                    | BitArrayMatchedValue::Discard(..)
                    | BitArrayMatchedValue::Assign { .. } => {
                        panic!("unreachable")
                    }
                },
            },

            // When checking on a tuple there's always going to be a single choice
            // and the code generation will always skip generating the check for it
            // as the type system ensures it must match.
            RuntimeCheck::Tuple { .. } => unreachable!("tried generating runtime check for tuple"),

            // Some variants like `Bool` and `Result` are special cased and checked
            // in a different way from all other variants.
            RuntimeCheck::Variant { match_, .. } if variable.type_.is_bool() => {
                match match_.used_name().as_str() {
                    "True" => value.to_doc(arena),
                    _ => docvec![arena, EXCLAMATION_MARK_DOCUMENT, value],
                }
            }

View on GitHub (pinned to 49f8762da5)