gleam-lang/gleam · error
Type has already checked to be valid
Error message
Type has already checked to be valid
What it means
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.
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
Example fix
// before (user code triggering inference hole)
let f = fn(x) { x }
f.field
// after
let f = fn(x) { x }
// f is a function; do not access fields on it — use a record instead Defensive patterns
Strategy: try-catch
Validate before calling
// Cannot validate; ensure field access is only used on record-typed values // assert inference: value must not be Fn/Var/Tuple before accessor lookup
Try / catch
// Panics abort the process; no catch. Verify with a fixed compiler version: // run `gleam build` on the snippet; if it panics, reduce and file an issue.
Prevention
- 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
When it happens
Trigger: 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.
Common situations: 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.
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
- invalid constants can not be in an untyped ast
- invalid expressions should not reach code generation
- invalid pattern size made it to code generation
- invalid segment type in exhaustiveness
- unexpected segment value pattern
AI-assisted analysis of gleam-lang/gleam@15b07c7830 (2026-09-14).
Data as JSON: /api/errors/4c2d19eb5039f0ad.
Report an issue: GitHub.
Appendix: source
Thrown at compiler-core/src/type_/expression.rs:2978
} => self
.environment
.importable_modules
.get(module)
.and_then(|module| module.accessors.get(name))
.filter(|accessors_map| {
accessors_map.publicity.is_importable()
|| module == &self.environment.current_module
})
.and_then(|accessors_map| {
Some((
accessors_map.type_.clone(),
accessors_map
.positional_accessors(inferred_variant.unwrap_or(0))?,
))
}),
Type::Fn { .. } | Type::Var { .. } | Type::Tuple { .. } => {
panic!("Type has already checked to be valid")
}
}
.expect("Variant has already checked to be valid");
// Positional fields must always be defined before any labelled fields.
// As such, we expect that field indices 0..(positional_fields.length)
// all correspond to positional fields. If this is not the case, then the
// user currently has a mistake in the definition of their custom type.
//
// However, we do not want to show an error here, because it would be
// confusing for the programmer. They can already see the error at the type
// definition site.
let type_ = if let Some(type_) = positional_fields.get(index as usize) {
type_.clone()
} else {
continue;
};
View on GitHub (pinned to 15b07c7830)