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

  1. Clear all build artifacts: `gleam clean && rm -rf build`, then rebuild from scratch.
  2. 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.
  3. Report the panic with the module source at github.com/gleam-lang/gleam — this expect should never fire given well-formed input.
  4. 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

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


AI-assisted analysis of gleam-lang/gleam@7e623aa83d (2026-08-17). Data as JSON: /api/errors/1df8f82ac25e7f58. Report an issue: GitHub.