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

  1. 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)
  2. Run `gleam clean` and rebuild to eliminate stale module metadata, and update dependencies (`gleam deps update`)
  3. 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

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


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 array

View on GitHub (pinned to 49f8762da5)