{"record":{"id":"2fbbfc18b764fd7b","repo":"gleam-lang/gleam","slug":"custom-type-variants-must-exist","errorCode":null,"errorMessage":"Custom type variants must exist","messagePattern":"Custom type variants must exist","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"compiler-core/src/exhaustiveness.rs","lineNumber":982,"sourceCode":"                ..\n            } if is_prelude_module(module) && name == \"List\" => BranchMode::List {\n                inner_type: arguments.first().expect(\"list has a type argument\").clone(),\n            },\n\n            Type::Tuple { elements } => BranchMode::Tuple {\n                elements: elements.clone(),\n            },\n\n            Type::Named {\n                module,\n                name,\n                arguments,\n                inferred_variant,\n                ..\n            } => {\n                let constructors = ConstructorSpecialiser::specialise_constructors(\n                    env.get_constructors_for_type(module, name)\n                        .expect(\"Custom type variants must exist\"),\n                    arguments.as_slice(),\n                    &env.current_module,\n                    module,\n                );\n\n                let inferred_variant = inferred_variant.map(|i| i as usize);\n                BranchMode::NamedType {\n                    constructors,\n                    inferred_variant,\n                }\n            }\n        }\n    }\n}\n\n/// When compiling a bit array pattern each segment is turned into a series of\n/// tests that all need to match in order for the pattern to succeed.\n/// Each segment might add some requirements on the total size of a bit array","sourceCodeStart":964,"sourceCodeEnd":1000,"githubUrl":"https://github.com/gleam-lang/gleam/blob/49f8762da595eb3c8f576656a4200a142ca188c9/compiler-core/src/exhaustiveness.rs#L964-L1000","documentation":"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.","triggerScenarios":"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).","commonSituations":"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.","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"],"exampleFix":"// before (Gleam)\npub type Wibble  // no constructors declared\ncase w { Wibble -> 1 }  // panic: variants must exist\n// after\npub type Wibble { Wibble Wobble }\ncase w { Wibble -> 1 | Wobble -> 2 }","handlingStrategy":"validation","validationCode":"// Gleam-side check before pattern matching on a custom type:\n// the matched type must be a custom type with at least one constructor;\n// `pub type Wibble` with no variants cannot be destructured.","typeGuard":null,"tryCatchPattern":"gleam build || { gleam clean && gleam build; } || echo \"persistent ICE: reduce snippet and file a bug\"","preventionTips":["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"],"tags":["rust","compiler","exhaustiveness","custom-types","invariant"],"backgroundTag":"internal-invariant-violation","analyzedSha":"49f8762da595eb3c8f576656a4200a142ca188c9","analyzedAt":"2026-09-14T11:14:59.388Z","contentChangedAt":"2026-09-14T11:14:59.388Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}