gleam-lang/gleam · error
Custom type variants must exist
Error message
Custom type variants must exist
What it means
During exhaustiveness checking of a match on a custom (named) type, the compiler fetches the type's constructors via `env.get_constructors_for_type(module, name).expect("Custom type variants must exist")`. By the time pattern matching is analysed, every referenced type must have registered constructor variants; if the lookup returns `None`, the compiler cannot specialise the constructors and panics instead of producing a user-facing diagnostic.
Solutions
- Ensure the matched type is a custom type with at least one variant defined before the `case` expression (a type alias or builtin like `Int` cannot be destructured)
- Run `gleam clean` and rebuild to eliminate stale module metadata, and update dependencies (`gleam deps update`)
- If reproducible on the latest Gleam, minimize the case and file a compiler bug with the type definition and match expression
Example fix
// before (Gleam)
pub type Wibble // no constructors declared
case w { Wibble -> 1 } // panic: variants must exist
// after
pub type Wibble { Wibble Wobble }
case w { Wibble -> 1 | Wobble -> 2 } Defensive patterns
Strategy: validation
Validate before calling
// Gleam-side check before pattern matching on a custom type: // the matched type must be a custom type with at least one constructor; // `pub type Wibble` with no variants cannot be destructured.
Try / catch
gleam build || { gleam clean && gleam build; } || echo "persistent ICE: reduce snippet and file a bug" Prevention
- Only pattern-match on custom types that declare at least one variant
- Declare constructors before the case expression and import the defining module explicitly
- Rebuild clean after dependency changes so constructor registrations are not stale
When it happens
Trigger: Analysing a `case` expression whose subject is a named custom type when `get_constructors_for_type` finds no entry — e.g. the type was declared but its variants never registered (analysis-order bug), the type comes from a module that failed to register constructors, or the type name resolves to something non-constructable (builtin type used in a pattern).
Common situations: Seen as a compiler ICE when pattern-matching on types defined in other modules or on types shadowing builtins on affected Gleam versions, or with cyclic/conditional imports that disturb constructor registration order.
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
- list has a type argument
- at least one choice
- bit array compilation with no choice
- check to already be a choice
- empty bit array test
AI-assisted analysis of gleam-lang/gleam@49f8762da5 (2026-09-14).
Data as JSON: /api/errors/2fbbfc18b764fd7b.
Report an issue: GitHub.
Appendix: source
Thrown at compiler-core/src/exhaustiveness.rs:982
..
} if is_prelude_module(module) && name == "List" => BranchMode::List {
inner_type: arguments.first().expect("list has a type argument").clone(),
},
Type::Tuple { elements } => BranchMode::Tuple {
elements: elements.clone(),
},
Type::Named {
module,
name,
arguments,
inferred_variant,
..
} => {
let constructors = ConstructorSpecialiser::specialise_constructors(
env.get_constructors_for_type(module, name)
.expect("Custom type variants must exist"),
arguments.as_slice(),
&env.current_module,
module,
);
let inferred_variant = inferred_variant.map(|i| i as usize);
BranchMode::NamedType {
constructors,
inferred_variant,
}
}
}
}
}
/// When compiling a bit array pattern each segment is turned into a series of
/// tests that all need to match in order for the pattern to succeed.
/// Each segment might add some requirements on the total size of a bit arrayView on GitHub (pinned to 49f8762da5)