{"record":{"id":"4c2d19eb5039f0ad","repo":"gleam-lang/gleam","slug":"type-has-already-checked-to-be-valid","errorCode":null,"errorMessage":"Type has already checked to be valid","messagePattern":"Type has already checked to be valid","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"compiler-core/src/type_/expression.rs","lineNumber":2978,"sourceCode":"                        } => self\n                            .environment\n                            .importable_modules\n                            .get(module)\n                            .and_then(|module| module.accessors.get(name))\n                            .filter(|accessors_map| {\n                                accessors_map.publicity.is_importable()\n                                    || module == &self.environment.current_module\n                            })\n                            .and_then(|accessors_map| {\n                                Some((\n                                    accessors_map.type_.clone(),\n                                    accessors_map\n                                        .positional_accessors(inferred_variant.unwrap_or(0))?,\n                                ))\n                            }),\n\n                        Type::Fn { .. } | Type::Var { .. } | Type::Tuple { .. } => {\n                            panic!(\"Type has already checked to be valid\")\n                        }\n                    }\n                    .expect(\"Variant has already checked to be valid\");\n\n                // Positional fields must always be defined before any labelled fields.\n                // As such, we expect that field indices 0..(positional_fields.length)\n                // all correspond to positional fields. If this is not the case, then the\n                // user currently has a mistake in the definition of their custom type.\n                //\n                // However, we do not want to show an error here, because it would be\n                // confusing for the programmer. They can already see the error at the type\n                // definition site.\n                let type_ = if let Some(type_) = positional_fields.get(index as usize) {\n                    type_.clone()\n                } else {\n                    continue;\n                };\n","sourceCodeStart":2960,"sourceCodeEnd":2996,"githubUrl":"https://github.com/gleam-lang/gleam/blob/15b07c783065c92bb016b1b74ed0995a5259850f/compiler-core/src/type_/expression.rs#L2960-L2996","documentation":"This panic fires in the Gleam compiler's field-access inference when a match on the inferred Type reaches an arm (Fn, Var, Tuple) that the earlier type-checking stages should have rejected as invalid for field access. The compiler asserts an internal invariant: by this point the type is guaranteed to be a Record with accessors. Hitting it means some other part of the type checker let an invalid type slip through.","triggerScenarios":"Accessing a field/position on a value whose inferred type is a function, type variable, or tuple after inference concludes; this indicates a bug in the exhaustiveness or inference logic upstream, not user error directly.","commonSituations":"Compiler bugs triggered by unusual code — e.g. accessing accessors on a value of polymorphic type where unification failed to concretize a Type::Var, or a regression after changing inference rules.","solutions":["Report the case to the Gleam compiler repository with the code snippet that triggers it","Check whether the code compiles with an older/newer Gleam version to identify a regression","Simplify the offending expression — often annotating the value with an explicit record type sidesteps the inference hole","Update the compiler to the latest patch, since unreachable-arm panics are usually fixed quickly"],"exampleFix":"// before (user code triggering inference hole)\nlet f = fn(x) { x }\nf.field\n// after\nlet f = fn(x) { x }\n// f is a function; do not access fields on it — use a record instead","handlingStrategy":"try-catch","validationCode":"// Cannot validate; ensure field access is only used on record-typed values\n// assert inference: value must not be Fn/Var/Tuple before accessor lookup","typeGuard":null,"tryCatchPattern":"// Panics abort the process; no catch. Verify with a fixed compiler version:\n// run `gleam build` on the snippet; if it panics, reduce and file an issue.","preventionTips":["Only use field/positional access on values you can annotate as records","Add explicit type annotations to values used with accessors","Keep the compiler updated; test upgrades before adopting new inference-dependent code","Reduce failing snippets and report them upstream immediately"],"tags":["compiler","panic","internal-invariant","type-inference"],"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"}