{"record":{"id":"86f7203b5a95ec8c","repo":"gleam-lang/gleam","slug":"could-not-lock-beam-compiler","errorCode":null,"errorMessage":"could not lock beam_compiler","messagePattern":"could not lock beam_compiler","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"critical","filePath":"compiler-cli/src/fs.rs","lineNumber":111,"sourceCode":"    beam_compiler: Arc<Mutex<Option<BeamCompilerInstance>>>,\n}\n\nimpl ProjectIO {\n    pub fn new() -> Self {\n        Self {\n            beam_compiler: Arc::new(Mutex::new(None)),\n        }\n    }\n\n    pub fn boxed() -> Box<Self> {\n        Box::new(Self::new())\n    }\n\n    pub(crate) fn initialise_beam_compiler(&self) -> Result<(), Error> {\n        let mut guard = self\n            .beam_compiler\n            .lock()\n            .expect(\"could not lock beam_compiler\");\n        if guard.is_none() {\n            *guard = Some(BeamCompilerInstance::new(self)?);\n        }\n        Ok(())\n    }\n}\n\nimpl FileSystemReader for ProjectIO {\n    fn read(&self, path: &Utf8Path) -> Result<String, Error> {\n        read(path)\n    }\n\n    fn read_bytes(&self, path: &Utf8Path) -> Result<Vec<u8>, Error> {\n        read_bytes(path)\n    }\n\n    fn is_file(&self, path: &Utf8Path) -> bool {\n        path.is_file()","sourceCodeStart":93,"sourceCodeEnd":129,"githubUrl":"https://github.com/gleam-lang/gleam/blob/7e623aa83da3776faee50ca4ab9a6c40124acd95/compiler-cli/src/fs.rs#L93-L129","documentation":"`ProjectIO` stores the persistent BEAM compiler handle in a `std::sync::Mutex<Option<BeamCompilerInstance>>` (imported at compiler-cli/src/fs.rs:23). `initialise_beam_compiler` (fs.rs:111) locks it, and `Mutex::lock()` only fails when the mutex is POISONED — some other thread panicked while holding the lock, typically the `panic!(\"BEAM compiler instance exited: ...\")` from beam_compiler.rs:45. The `.expect(\"could not lock beam_compiler\")` therefore aborts as a follow-on symptom of an earlier panic in the same process.","triggerScenarios":"Any earlier panic while this lock is held: the BEAM helper process dying mid-compile, or a panic while constructing `BeamCompilerInstance`. Afterwards every `initialise_beam_compiler` call in the same process panics too — mostly visible in the long-lived Gleam language server, where one poisoned lock breaks all later compiles until restart.","commonSituations":"Gleam LSP in an editor that stays open across an Erlang outage/upgrade; a build session whose escript helper was OOM-killed followed by another compile in the same process; flaky sandboxed environments killing the BEAM child.","solutions":["Restart the process: re-run the CLI command, or restart the Gleam LSP/editor — poisoning lasts only for the process lifetime","Find and fix the ORIGINAL panic in the logs above this one (usually 'BEAM compiler instance exited: ...'): verify Erlang health and check for OOM kills","Re-run the build after the environment is fixed; the new process re-creates the BEAM instance cleanly","Report repeatable poisoning chains at https://github.com/gleam-lang/gleam/issues with both panic messages"],"exampleFix":null,"handlingStrategy":"retry","validationCode":null,"typeGuard":null,"tryCatchPattern":null,"preventionTips":["Treat 'could not lock beam_compiler' as a symptom: search the log upward for the first panic (usually the BEAM instance exiting) and fix that","Restart the Gleam LSP after Erlang changes or any visible BEAM crash","Keep Erlang healthy and memory headroom available so the original panic never fires"],"tags":["gleam","rust","mutex","poisoning","lsp","build","beam"],"backgroundTag":"mutex-poisoned","analyzedSha":"7e623aa83da3776faee50ca4ab9a6c40124acd95","analyzedAt":"2026-08-17T00:07:02.091Z","schemaVersion":2},"datasetVersion":"2026-08-17T04:17:16.089Z"}