gleam-lang/gleam · error
empty bit array test
Error message
empty bit array test
What it means
Panic when starting a bit-array decision node with no existing choices: the pivot test is taken from the front of the pending `tests` deque, and this `expect` fires when that deque is empty. The invariant is that any branch reaching bit-array compilation has at least one pending bit-array segment test.
Solutions
- Ensure at least one value test is generated per bit-array pattern; if a pattern has no tests, treat it as a catch-all instead of entering the pivot path.
- Fix segment lowering so trivially-true segments do not push empty test lists while still entering this compiler path.
- Short-circuit: if `tests` is empty, add the branch as unconditional rather than selecting a pivot.
Example fix
// before
let test = tests.front().expect("empty bit array test").clone();
// after
let Some(test) = tests.front() else {
panic!("bit array pattern produced no tests; cannot choose pivot")
};
let test = test.clone(); Defensive patterns
Strategy: validation
Validate before calling
if tests.is_empty() {
// no pivot possible: treat pattern as unconditional/catch-all and skip pivot selection
} Type guard
fn has_pivot_test(tests: &VecDeque<BitArrayTest>) -> bool { !tests.is_empty() } Try / catch
std::panic::catch_unwind(|| compile_bit_array_node(node)).map_err(|_| Bug::EmptyBitArrayTest)
Prevention
- Guarantee at least one value test per bit-array pattern segment lowering.
- Route test-less bit-array patterns through the catch-all path, not the pivot path.
- Unit-test bit arrays with only size/flags segments.
When it happens
Trigger: Compiling a case subject with bit-array patterns where all pending tests were already consumed (e.g. empty segment list, or every branch's first segment produced no test), so `tests.front()` is None at the pivot-selection point.
Common situations: Gleam compiler contributors hit this with bit-array patterns containing only size/width segments without value tests, or after changes to how bit-array segment tests are generated (`is_bit_array_test`/segment lowering).
Understand the failure class
Background: "must not be empty", "cannot be empty" — required-field validation errors across open-source libraries — this error's family across 41 libraries.
Related errors
- bit array compilation with no choice
- at least one choice
- check to already be a choice
- no unconditional patterns left
- pattern index
AI-assisted analysis of gleam-lang/gleam@49f8762da5 (2026-09-14).
Data as JSON: /api/errors/ac9e140541fb3492.
Report an issue: GitHub.
Appendix: source
Thrown at compiler-core/src/exhaustiveness.rs:3213
/// One path is going to be for the branches that can match if the test is
/// successful, and the other one is going to be the usual fallback to go
/// down to if it's not successful.
///
/// > "And now for the tricky bit..."
/// > <https://youtu.be/lKXe3HUG2l4?si=i1thYB-kjfMU8NSe&t=645>
///
fn add_checked_bit_array_branch(
&mut self,
pattern_check: PatternCheck,
mut tests: VecDeque<BitArrayTest>,
mut branch: Branch,
compiler: &mut Compiler<'_>,
) {
// If we haven't found a test yet we just use the first one we find
// as the pivot to split all the branches.
let pivot_test = match self.choices.as_slice() {
[] => {
let test = tests.front().expect("empty bit array test").clone();
self.choices.push((
RuntimeCheck::BitArray { test: test.clone() },
VecDeque::new(),
));
test
}
[(RuntimeCheck::BitArray { test }, _)] => test.clone(),
_ => unreachable!("non bit array check when splitting bit array patterns"),
};
let pattern_fails_if_test_succeeds = tests
.iter()
.any(|test| test.fails_if_succeeding(&pivot_test).is_certain());
let pattern_fails_if_test_fails = tests
.iter()
.any(|test| test.fails_if_failing(&pivot_test).is_certain());
View on GitHub (pinned to 49f8762da5)