gleam-lang/gleam · error
invalid constants can not be in an untyped ast
Error message
invalid constants can not be in an untyped ast
What it means
An internal invariant panic in Gleam's constant inference (`constant.rs:535`, `do_infer`). Constants carrying `Constant::Invalid` are sentinel nodes produced by the parser/error-recovery for syntactically invalid constants; they should be filtered out before type inference runs. Reaching inference with one means the untyped AST still contains an error placeholder, so inference cannot proceed and panics.
Solutions
- Fix the syntax error in the offending constant definition in your Gleam source — the compiler's error output should point near it.
- Rewrite the constant with valid literal/constructor syntax and recompile.
- If you believe the constant is valid, report a compiler bug with the source snippet — `Invalid` nodes should have produced a parse error or been filtered, not panicked.
- If developing the compiler, ensure `Constant::Invalid` nodes are filtered from the AST before inference, or make `do_infer` return a type error instead of panicking.
Example fix
// before (Gleam source with invalid constant) const x: Int = not_a_valid_constant(] // after const x: Int = 42
Defensive patterns
Strategy: validation
Validate before calling
// Rust (compiler-side): filter invalid constants before inference
let constants: Vec<_> = constants
.into_iter()
.filter(|c| !matches!(c, Constant::Invalid { .. }))
.collect(); Type guard
fn is_inferable(c: &TypedConstant) -> bool {
!matches!(c, Constant::Invalid { .. })
} Try / catch
// Panics are not recoverable; gate inference on the guard
if !is_inferable(constant) {
return; // or emit a diagnostic instead of inferring
} Prevention
- Fix constant syntax errors reported by the parser before relying on type-check output.
- Ensure error-recovery placeholders (`Constant::Invalid`) are pruned from the AST before the typing phase.
- When adding new constant syntax, test that malformed forms produce diagnostics, not inference panics.
When it happens
Trigger: Type inference (`infer`, `do_infer`, `infer_record`, `infer_tuple`, `infer_list`, `infer_string_concatenation`) encounters a `Constant::Invalid` node — e.g. a module constant or record/tuple/list element whose constant expression failed to parse but was not dropped before typing.
Common situations: Compiling a module with a malformed constant (bad literal, invalid record constructor syntax) where error recovery leaves an `Invalid` placeholder in a nested constant position; compiler development adding new constant forms; compiler bugs where `Invalid` nodes propagate into nested structures.
Understand the failure class
Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.
Related errors
- Expression not fully reduced.
- Token could not be converted to binop.
- Tried to reduce bit array size without 2 operands
- Tried to reduce without 2 expressions
- Tried to reduce without 2 guards
AI-assisted analysis of gleam-lang/gleam@49f8762da5 (2026-09-14).
Data as JSON: /api/errors/3ac838b78d2b4b45.
Report an issue: GitHub.
Appendix: source
Thrown at compiler-core/src/type_/constant.rs:553
.problems
.error(convert_unify_error(error, message.location()));
}
Box::new(message)
});
// Constant todos always result in a compile time error, this
// way the developer has to remember to change them before
// running their code!
self.typer.problems.error(Error::TodoConstant { location });
Constant::Todo {
location,
type_,
message,
}
}
Constant::Invalid { .. } => panic!("invalid constants can not be in an untyped ast"),
}
}
fn infer_string_concatenation(
&mut self,
location: SrcSpan,
operator_start: u32,
left: UntypedConstant,
right: UntypedConstant,
operator: BinOp,
) -> TypedConstant {
self.typer
.track_feature_usage(FeatureKind::ConstantStringConcatenation, location);
let left = self.do_infer(left);
if let Err(error) = unify(string(), left.type_()) {
self.typer.problems.error(
errorView on GitHub (pinned to 49f8762da5)