{"record":{"id":"d688315de4cd0b50","repo":"gleam-lang/gleam","slug":"custom-type-constructor-exist-for-type","errorCode":null,"errorMessage":"Custom type constructor exist for type","messagePattern":"Custom type constructor exist for type","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"compiler-core/src/exhaustiveness/missing_patterns.rs","lineNumber":189,"sourceCode":"\n            RuntimeCheck::Variant {\n                index,\n                fields,\n                labels,\n                ..\n            } => {\n                let (module, name) = variable\n                    .type_\n                    .named_type_name()\n                    .expect(\"Should be a named type\");\n\n                let name = self\n                    .environment\n                    .get_constructors_for_type(&module, &name)\n                    .expect(\"Custom type constructor must have custom type kind\")\n                    .variants\n                    .get(*index)\n                    .expect(\"Custom type constructor exist for type\")\n                    .name\n                    .clone();\n\n                let fields = fields\n                    .iter()\n                    .enumerate()\n                    .map(|(index, variable)| VariantField {\n                        label: labels.get(&index).cloned(),\n                        variable: variable.clone(),\n                    })\n                    .collect();\n\n                Term::Variant {\n                    variable,\n                    name,\n                    module,\n                    fields,\n                }","sourceCodeStart":171,"sourceCodeEnd":207,"githubUrl":"https://github.com/gleam-lang/gleam/blob/15b07c783065c92bb016b1b74ed0995a5259850f/compiler-core/src/exhaustiveness/missing_patterns.rs#L171-L207","documentation":"In the same constructor-to-term conversion, `variants.get(*index).expect(\"Custom type constructor exist for type\")` panics when the recorded constructor index is out of bounds for the type's variant list. The invariant is that any constructor check's index refers to an existing variant of its type.","triggerScenarios":"A decision-tree check stores a constructor index captured before the environment's variant list changed (re-ordering, filtering, or registration of fewer variants), so `get(*index)` returns None.","commonSituations":"Hit by compiler contributors after changing variant registration order, dropping unreachable variants, or when module recompilation mixes stale indices with a rebuilt environment.","solutions":["Ensure the same environment population order is used when building checks and when converting them back to terms","Validate `index < variants.len()` when creating constructor checks to fail earlier with context","If variants are filtered, remap indices instead of leaving gaps","End users: file a compiler bug with the multi-constructor type and match that triggers it"],"exampleFix":"// before\n.expect(\"Custom type constructor exist for type\")\n// after\n.unwrap_or_else(|| panic!(\"constructor index {} out of range for type {}::{} (has {} variants)\", index, module, name, variants.len()))","handlingStrategy":"validation","validationCode":"if *index >= variants.len() {\n    return Err(Error::ConstructorIndexOutOfRange { index, variants: variants.len() });\n}","typeGuard":"fn valid_variant_index(index: usize, variants: &[Variant]) -> bool { index < variants.len() }","tryCatchPattern":null,"preventionTips":["Validate constructor indices at check-creation time","Never filter or reorder variants after indices are recorded; remap instead","Use identical environment-population code paths for checking and term conversion"],"tags":["rust","compiler","pattern-matching","panic"],"backgroundTag":"internal-invariant-violation","analyzedSha":"15b07c783065c92bb016b1b74ed0995a5259850f","analyzedAt":"2026-09-14T11:14:59.388Z","contentChangedAt":"2026-09-14T11:14:59.388Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}