gleam-lang/gleam · error
Type-checking ensured that the body has at least 1 statement
Error message
Type-checking ensured that the body has at least 1 statement
What it means
When the compiler serializes inlinable functions back out of the analysis phase, it converts the stored body statements into the NonEmpty TypedStatements type with body.try_into().expect("Type-checking ensured that the body has at least 1 statement") (inline.rs:1838). Because Gleam grammars require every function body to have at least one expression, an empty body can only come from malformed serialized/cached data — another internal-compiler-error class panic rather than a user mistake.
Source
Thrown at compiler-core/src/inline.rs:1838
/// Converts an `InlinableFunction` to an anonymous function, which can then
/// be inlined within another function.
fn to_anonymous_function(&self) -> (Vec<TypedArg>, Vec1<TypedStatement>) {
let parameters = self
.parameters
.iter()
.map(|parameter| parameter.to_typed_arg())
.collect();
let body = self
.body
.iter()
.map(|ast| Statement::Expression(ast.to_expression()))
.collect_vec();
(
parameters,
body.try_into()
.expect("Type-checking ensured that the body has at least 1 statement"),
)
}
}
#[derive(Debug, Clone, PartialEq, Eq, serde::Serialize, serde::Deserialize)]
pub enum InlinableExpression {
Case {
subjects: Vec<InlinableExpression>,
clauses: Vec<InlinableClause>,
compiled_case: Box<CompiledCase>,
type_: InlinableType,
},
Variable {
name: EcoString,
constructor: InlinableValueConstructor,
type_: InlinableType,
},View on GitHub (pinned to 7e623aa83d)
Solutions
- Clear all build artifacts: `gleam clean && rm -rf build`, then rebuild from scratch.
- Reproduce on a single clean checkout to confirm cache vs code: if it still panics, downgrade/upgrade gleam and check the release notes for inliner fixes.
- Report the panic with the module source at github.com/gleam-lang/gleam — this expect should never fire given well-formed input.
- For embedders running gleam_core in-process, isolate compilation in a subprocess so an ICE cannot take down your host.
Defensive patterns
Strategy: validation
Validate before calling
// Maintainers/embedders of the inliner: validate deserialized bodies before
// the NonEmpty conversion instead of relying on the expect.
if body.is_empty() {
return Err(corrupt_cache_error(module)); // rebuild this package from source
}
let body: NonEmptyTypedStatements = body.try_into().expect("checked non-empty above"); Prevention
- Never share or persist `build/` directories between different gleam versions.
- Add `gleam clean` to scripts that switch toolchains (mise/asdf/gleam-toolchain hooks).
- Treat this panic as data corruption: wipe caches, rebuild, and only then file an upstream issue.
When it happens
Trigger: The InlinableFunction's stored body deserializes to an empty statements vec — corrupted or version-skewed incremental build caches, or a bug in the code that produces InlinableFunction bodies upstream.
Common situations: Build directories shared or cached between different gleam versions (CI caches, network filesystems), interrupted builds leaving half-written cache files, or hitting a new inliner regression after upgrading.
Related errors
- Type checking ensures there is at least one statement
- Custom type must have at least one definition here
- `panic` expression evaluated.
- Non-UTF8 path in hardlink_dir
- Writing warning to stderr
AI-assisted analysis of gleam-lang/gleam@7e623aa83d (2026-08-17).
Data as JSON: /api/errors/1df8f82ac25e7f58.
Report an issue: GitHub.