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

  1. Re-run the build; a transient BEAM crash is usually resolved by a fresh compiler instance.
  2. Check Erlang/OTP is installed and on PATH at a version gleam supports (gleam --version; erl -version).
  3. Look for OOM-killer or signal kills of the escript process in system logs (dmesg / journalctl) and raise memory limits.
  4. Update gleam to the latest version in case the BEAM instance crash is a known fixed bug.
  5. 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

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


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)