gleam-lang/gleam · error
invalid expressions should not reach code generation
Error message
invalid expressions should not reach code generation
What it means
The Gleam JavaScript code generator asserts that an `TypedExpr::Invalid` expression (a placeholder produced by the parser/type checker after a syntax or type error) never reaches code generation. Hitting this panic means an internal compiler invariant was broken: error recovery failed to stop compilation before the JavaScript backend ran.
Solutions
- Fix all syntax and type errors in the module before running code generation (run `gleam check` / the parse+typecheck passes first).
- If using compiler internals, ensure you abort the pipeline when error_count > 0 instead of calling the JavaScript generator.
- If all your code is valid and this still fires, it is a compiler bug — report it to the Gleam repository with a minimal reproducing module.
Example fix
// before (embedding the compiler)
let module = compile(src);
let js = javascript::compile(&module); // panics on Invalid nodes
// after
let module = compile(src);
if module.has_errors() { return Err(...); }
let js = javascript::compile(&module); Defensive patterns
Strategy: validation
Validate before calling
// gleam_core usage: abort before codegen if the module has errors
if module.has_errors() || module.ast.iter().any(|e| matches!(e, TypedExpr::Invalid{..})) {
return Err(Error::parse_failed());
} Type guard
fn is_codegen_safe(expr: &TypedExpr) -> bool {
!matches!(expr, TypedExpr::Invalid { .. })
} Try / catch
match std::panic::catch_unwind(|| javascript::compile(&module)) {
Ok(doc) => doc,
Err(_) => report_internal_compiler_bug(),
} Prevention
- Always run parse + typecheck and abort on error before invoking any backend codegen.
- When embedding the compiler, treat panics as compiler bugs and capture panic messages for bug reports.
- Keep Gleam compiler versions in sync across workspace tooling.
When it happens
Trigger: Calling the JavaScript code generation pass on a module whose AST still contains `TypedExpr::Invalid` nodes — i.e. generating code for a module that was not fully parsed/type-checked, or using compiler internals/library APIs to feed a partially-invalid AST straight into `expression()`.
Common situations: Embedding the Gleam compiler as a library (e.g. in tooling or LSP-like integrations) and invoking codegen without first checking for parse/type errors; compiler bugs where error recovery produced an Invalid node that wasn't pruned.
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 bit array segment type reached code generation
- invalid constants should not reach code generation
- invalid pattern size made it to code generation
- invalid segment type in exhaustiveness
- record updates should not reach code generation
AI-assisted analysis of gleam-lang/gleam@49f8762da5 (2026-09-14).
Data as JSON: /api/errors/cb34fa290027105d.
Report an issue: GitHub.
Appendix: source
Thrown at compiler-core/src/javascript/expression.rs:531
self.negate_with(arena, MINUS_SPACE_DOCUMENT, value)
}
TypedExpr::Echo {
expression,
message,
location,
..
} => {
let expression = expression
.as_ref()
.expect("echo with no expression outside of pipe");
let expresion_doc =
self.not_in_tail_position(None, |this| this.wrap_expression(arena, expression));
self.echo(arena, expresion_doc, message.as_deref(), location)
}
TypedExpr::Invalid { .. } => {
panic!("invalid expressions should not reach code generation")
}
};
if let Position::Statement = self.scope_position
&& expression_requires_semicolon(expression)
{
document = document.append(arena, SEMICOLON_DOCUMENT);
}
if expression.handles_own_return() {
docvec![
arena,
self.source_map_tracker(arena, expression.location().start),
document
]
} else {
docvec![
arena,
self.source_map_tracker(arena, expression.location().start),
self.wrap_return(arena, document)View on GitHub (pinned to 49f8762da5)