gleam-lang/gleam · error
BEAM compiler instance exited
Error message
BEAM compiler instance exited: {status} What it means
The long-lived persistent Erlang/BEAM compiler instance that gleam uses to compile projects has terminated before this compilation request was sent to it. The library deliberately panics rather than send work to a dead process, because compilation could not possibly succeed. This usually means the escript/node child process crashed, was killed (OOM, signal), or exited early due to a bad environment.
Solutions
- Re-run the build; a transient BEAM crash is usually resolved by a fresh compiler instance.
- Check Erlang/OTP is installed and on PATH at a version gleam supports (gleam --version; erl -version).
- Look for OOM-killer or signal kills of the escript process in system logs (dmesg / journalctl) and raise memory limits.
- Update gleam to the latest version in case the BEAM instance crash is a known fixed bug.
- If reproducible, capture the crashing input and file an issue at github.com/gleam-lang/gleam.
Example fix
// before: reusing a cached compiler instance across builds let compiler = cache.get_beam_compiler(); compiler.compile(lib)?; // after: recreate the instance when the previous one has exited let mut compiler = BeamCompiler::new(...); compiler.compile(lib)?;
Defensive patterns
Strategy: retry
Validate before calling
// Check the BEAM instance is alive before compiling
if let Some(status) = beam_compiler.process.try_wait().ok().flatten() {
eprintln!("BEAM instance already exited: {status}; recreating");
beam_compiler = BeamCompiler::new(...)?;
} Type guard
fn is_alive(p: &mut Child) -> bool { matches!(p.try_wait(), Ok(None)) } Try / catch
match beam_compiler.compile(lib) {
Ok(out) => out,
Err(e) if e.to_string().contains("BEAM compiler instance exited") => {
let mut fresh = BeamCompiler::new(...)?;
fresh.compile(lib)?
}
} Prevention
- Verify Erlang/OTP is installed and on PATH before running builds.
- Run builds with adequate memory headroom; watch for OOM kills of the escript process.
- Don't reuse compiler instances across builds after a failure; recreate them.
- Keep gleam and OTP versions aligned and up to date.
When it happens
Trigger: Calling compile on a BeamCompiler whose child process has already exited; detected via process.try_wait() returning Some(status) at the start of compile.
Common situations: Running out of memory so the OS kills the BEAM VM; an incompatible or missing Erlang installation; the BEAM instance crashing on malformed input; reusing a compiler instance after a previous fatal failure; container/CPU limits terminating the subprocess.
Related errors
- at least one choice
- bit array compilation with no choice
- case with no subjects
- check to already be a choice
- Custom type constructor exist for type
AI-assisted analysis of gleam-lang/gleam@15b07c7830 (2026-09-14).
Data as JSON: /api/errors/5e2a95e8f67b0907.
Report an issue: GitHub.
Appendix: source
Thrown at compiler-cli/src/beam_compiler.rs:45
// A guard held for cleaning up the temporary file used to start the BEAM instance.
_source: tempfile::NamedTempFile,
}
impl BeamCompilerInstance {
pub fn compile(
&mut self,
out: &Utf8Path,
lib: &Utf8Path,
modules: &HashSet<Utf8PathBuf>,
stdio: Stdio,
) -> Result<Vec<String>, Error> {
// Check that the BEAM instance is still alive before attempting to use it.
let exit_status = self
.process
.try_wait()
.expect("access BEAM instance exit state");
if let Some(status) = exit_status {
panic!("BEAM compiler instance exited: {status}");
}
// Prepare work to send to the BEAM instance.
let args = format!(
"{{\"{}\", \"{}\", [\"{}\"]}}",
escape_path(lib),
escape_path(out.join("ebin")),
modules
.iter()
.map(|module| escape_path(out.join(paths::ARTEFACT_DIRECTORY_NAME).join(module)))
.join("\", \"")
);
tracing::debug!(args=?args, "call_beam_compiler");
writeln!(self.stdin.as_ref().expect("stdin present"), "{args}.").map_err(|error| {
Error::ShellCommand {
program: "escript".into(),View on GitHub (pinned to 15b07c7830)