gleam-lang/gleam · critical

BEAM compiler instance exited: {status}

Error message

BEAM compiler instance exited: {status}

What it means

Gleam keeps one long-lived Erlang/BEAM helper process (an escript started by `BeamCompilerInstance::new`) to compile .erl modules quickly. Before every request `BeamCompilerInstance::compile` calls `try_wait()` (compiler-cli/src/beam_compiler.rs:40-46); if the child has already exited it panics `BEAM compiler instance exited: {status}`. This is a broken-invariant abort — the compiler assumes its helper survives the whole session — and it takes down the `gleam` process.

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(|e| {
            Error::ShellCommand {
                program: "escript".into(),

View on GitHub (pinned to 7e623aa83d)

Solutions

  1. Verify Erlang works outside Gleam: `command -v escript` and `erl -noshell -eval 'io:format("ok~n").' -s init stop`
  2. Check for resource kills: `dmesg | grep -i -E 'oom|killed process'` or container runtime events; raise memory/pids limits
  3. Re-run the command — a fresh `gleam` invocation spawns a new BEAM instance; for the LSP, restart the editor or language server
  4. If it reproduces with healthy Erlang and no OOM, capture the exit status from the panic text and report it at https://github.com/gleam-lang/gleam/issues
Defensive patterns

Strategy: validation

Validate before calling

# verify Erlang can host the BEAM helper before building
command -v escript >/dev/null 2>&1 || { echo 'escript not on PATH'; exit 1; }
erl -noshell -eval 'io:format("erlang ok~n").' -s init stop || { echo 'erl unusable'; exit 1; }
gleam build

Prevention

When it happens

Trigger: The BEAM child dies between or during compile requests: the kernel OOM killer or a container memory limit kills escript, Erlang was uninstalled or corrupted while the session ran, security software kills the helper process, or the machine is unstable. (The adjacent `expect("access BEAM instance exit state")` is a separate near-impossible waitpid failure.)

Common situations: CI containers with tight `--memory`/`--pids-limit`; Docker/gVisor sandboxes where escript crashes; antivirus reaping child processes on Windows; a partially upgraded Erlang install; a long-lived Gleam LSP session spanning an Erlang upgrade or outage.

Related errors


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