{"record":{"id":"11c7be67cd0d1fd5","repo":"gleam-lang/gleam","slug":"inmemoryfile-into-content-called-with-multiple-re","errorCode":null,"errorMessage":"InMemoryFile::into_content called with multiple references","messagePattern":"InMemoryFile::into_content called with multiple references","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"compiler-core/src/io/memory.rs","lineNumber":402,"sourceCode":"            ..Self::default()\n        }\n    }\n\n    /// Checks whether this is a directory's entry.\n    pub fn is_directory(&self) -> bool {\n        matches!(self.node, InMemoryFileNode::Directory)\n    }\n\n    /// Returns this file's contents if this is not a directory.\n    ///\n    /// # Panics\n    ///\n    /// Panics if this is not the only reference to the underlying files.\n    ///\n    pub fn into_content(self) -> Option<Content> {\n        let buffer = self.node.into_file_buffer()?;\n        let contents = Rc::try_unwrap(buffer)\n            .expect(\"InMemoryFile::into_content called with multiple references\")\n            .into_inner();\n\n        // All null bytes are usually from when a binary file is empty, and\n        // aren't particularly useful as text, so we treat them as binary.\n        if contents.iter().all(|byte| *byte == 0) {\n            return Some(Content::Binary(contents));\n        }\n\n        match String::from_utf8(contents) {\n            Ok(s) => Some(Content::Text(s)),\n            Err(e) => Some(Content::Binary(e.into_bytes())),\n        }\n    }\n}\n\nimpl Default for InMemoryFile {\n    fn default() -> Self {\n        Self {","sourceCodeStart":384,"sourceCodeEnd":420,"githubUrl":"https://github.com/gleam-lang/gleam/blob/7e623aa83da3776faee50ca4ab9a6c40124acd95/compiler-core/src/io/memory.rs#L384-L420","documentation":"InMemoryFile::into_content (memory.rs:402) unwraps the file's Rc<RefCell<Vec<u8>>> buffer with Rc::try_unwrap(...).expect(\"InMemoryFile::into_content called with multiple references\"). The buffer Rc gains extra owners whenever a reader/writer handle to that in-memory file is cloned and still alive, so into_content enforces sole-ownership exactly like InMemoryFileSystem::into_contents (error 34), but per file.","triggerScenarios":"Opening the same in-memory path multiple times (each open_read/open_write returns handles sharing the buffer), keeping one handle alive in a variable or struct, and then calling into_contents()/into_content() on the filesystem/file while the handle is still referenced.","commonSituations":"Tests that keep an io::Handle around for assertions after the compiler wrote files, or wrapper FileSystems (e.g. wasm_filesystem.rs delegating to the imfs) that retain handles past the final into_contents call.","solutions":["Drop all open handles for the path before converting: `drop(reader); drop(writer);` then call into_contents().","Prefer read_bytes()/files() for inspection so no ownership conversion is needed.","Scope handles tightly (inside a block or function) so they die before the into_contents call site.","Maintainer option: make into_content return Result<Option<Content>> or expose strong_count for pre-checking."],"exampleFix":"// before: handle still alive during conversion\nlet mut w = fs.writer(&path);\nw.write(&path, \"data\")?;\nlet files = fs.into_contents(); // panics: buffer Rc shared with w\n\n// after: release handles first\n{\n    let mut w = fs.writer(&path);\n    w.write(&path, \"data\")?;\n} // handle dropped here\nlet files = fs.into_contents();","handlingStrategy":"validation","validationCode":"// Drop all open handles for in-memory paths before the final conversion\n{\n    let mut w = fs.writer(&path);\n    w.write(&path, &contents)?;\n} // writer (and any readers) dropped here — buffer Rc count back to 1\nlet files = fs.into_contents();","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Scope every reader/writer handle tightly so it cannot outlive into_contents().","Don't store io handles in long-lived structs when you plan to consume the filesystem afterwards.","Use read_bytes()/files() for inspection to avoid ownership conversion entirely."],"tags":["panic","rc","try-unwrap","in-memory-fs","file-handles","tests","gleam-core"],"backgroundTag":"rc-try-unwrap-panic","analyzedSha":"7e623aa83da3776faee50ca4ab9a6c40124acd95","analyzedAt":"2026-08-17T00:07:02.091Z","schemaVersion":2},"datasetVersion":"2026-08-17T04:17:16.089Z"}