{"record":{"id":"61687e7c05dea61b","repo":"gleam-lang/gleam","slug":"type-checking-ensures-there-is-at-least-one-statem","errorCode":null,"errorMessage":"Type checking ensures there is at least one statement","messagePattern":"Type checking ensures there is at least one statement","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"compiler-core/src/inline.rs","lineNumber":1026,"sourceCode":"        self.position = Position::InlinedFunction;\n        let variables = self.renamed_variables.clone();\n\n        // Perform inlining on each of the statements in this function's body,\n        // potentially inlining parameters and function calls inside this function.\n        statements.extend(body.into_iter().map(|statement| self.statement(statement)));\n\n        // Restore scope\n        self.inline_variables = inline_variables;\n        self.position = position;\n        self.renamed_variables = variables;\n\n        // We try to expand this block, so a function which is inlined as a\n        // single expression does not get wrapped unnecessarily\n        expand_block(TypedExpr::Block {\n            location: BLANK_LOCATION,\n            statements: statements\n                .try_into()\n                .expect(\"Type checking ensures there is at least one statement\"),\n        })\n    }\n\n    fn pipeline(\n        &mut self,\n        location: SrcSpan,\n        first_value: TypedPipelineAssignment,\n        assignments: Vec<(TypedPipelineAssignment, PipelineAssignmentKind)>,\n        finally: Box<TypedExpr>,\n        finally_kind: PipelineAssignmentKind,\n    ) -> TypedExpr {\n        let first_value = self.pipeline_assignment(first_value);\n        let assignments = assignments\n            .into_iter()\n            .map(|(assignment, kind)| (self.pipeline_assignment(assignment), kind))\n            .collect();\n        let finally = self.boxed_expression(finally);\n","sourceCodeStart":1008,"sourceCodeEnd":1044,"githubUrl":"https://github.com/gleam-lang/gleam/blob/7e623aa83da3776faee50ca4ab9a6c40124acd95/compiler-core/src/inline.rs#L1008-L1044","documentation":"The cross-module function inliner stores inlined statement lists as Vec<TypedStatement> and converts them into the NonEmptyStatements type with try_into().expect(\"Type checking ensures there is at least one statement\") (inline.rs:1026). Gleam function bodies always contain at least one expression after parsing/type-checking, so an empty list here means an internal invariant broke — an internal compiler error (ICE), not something caused by your project configuration.","triggerScenarios":"Compiling code whose inlinable function body round-trips through the incremental build cache with zero statements — typically a stale/corrupted build directory after a compiler upgrade, or an inliner bug on an unusual expression shape (e.g. a function body that became empty after inlining substitutions).","commonSituations":"Upgrading gleam versions but keeping the old `build/` directory; CI caches (actions/cache over build/) reused across toolchain updates; exotic pipelines/case expressions exercising inliner edge cases.","solutions":["Delete the build cache and rebuild: `rm -rf build && gleam build` — this is the fix for the stale-cache variant.","Pin the compiler version that previously worked (`gleam-toolchain`/mise/asdf) until you can upgrade to a release with the fix.","If it reproduces on a clean build, minimize the failing module and report it with the panic backtrace at github.com/gleam-lang/gleam.","As a workaround, stop the function from being inlined: make it non-trivial or move it out of the cross-module inline path (e.g. avoid marking it for inlining)."],"exampleFix":"# before: stale artifacts from an older compiler\nrm -rf build  # forgotten after `gleam` upgrade\n\n# after: always clear generated code caches across toolchain changes\nrm -rf build && gleam clean && gleam build","handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"// Tooling that drives gleam_core's build in-process: isolate ICEs so a\n// compiler bug is reportable instead of fatal.\nlet result = std::panic::catch_unwind(std::panic::AssertUnwindSafe(|| {\n    build::main(paths, options)\n}));\nmatch result {\n    Ok(Ok(())) => {}\n    Ok(Err(e)) => eprintln!(\"gleam error: {e:?}\"),\n    Err(payload) => eprintln!(\"internal compiler error: {payload:?} — please report with backtrace\"),\n}","preventionTips":["Delete `build/` (and CI caches over it) whenever the gleam version changes.","Pin the compiler version in CI so caches are never reused across toolchain upgrades.","When an ICE appears, first reproduce on a clean checkout to classify cache-skew vs real bug before reporting."],"tags":["panic","internal-compiler-error","inliner","incremental-cache","nonempty","build-cache"],"backgroundTag":"compiler-internal-error","analyzedSha":"7e623aa83da3776faee50ca4ab9a6c40124acd95","analyzedAt":"2026-08-17T00:07:02.091Z","schemaVersion":2},"datasetVersion":"2026-08-17T04:17:16.089Z"}