{"record":{"id":"8a92cd0ea1b12240","repo":"sinelaw/fresh","slug":"buffer-has-unsaved-changes","errorCode":null,"errorMessage":"Buffer has unsaved changes","messagePattern":"Buffer has unsaved changes","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/fresh-editor/src/app/buffer_close.rs","lineNumber":44,"sourceCode":"    /// Set when the LRU landing target was a buffer *group* rather than a\n    /// buffer: `buffer` is then only housekeeping and the caller re-activates\n    /// the group tab on this leaf.\n    return_to_group: Option<LeafId>,\n}\n\nimpl Editor {\n    /// Close the given buffer\n    pub fn close_buffer(&mut self, id: BufferId) -> anyhow::Result<()> {\n        // Check for unsaved changes\n        if let Some(state) = self\n            .windows\n            .get(&self.active_window)\n            .map(|w| &w.buffers)\n            .expect(\"active window present\")\n            .get(&id)\n        {\n            if state.buffer.is_modified() {\n                return Err(anyhow::anyhow!(\"Buffer has unsaved changes\"));\n            }\n        }\n        self.close_buffer_internal(id, false)\n    }\n\n    /// Force close the given buffer without checking for unsaved changes\n    /// Use this when the user has already confirmed they want to discard changes\n    pub fn force_close_buffer(&mut self, id: BufferId) -> anyhow::Result<()> {\n        self.close_buffer_internal(id, false)\n    }\n\n    /// Close the last editor tab while a Utility Dock is present, keeping the\n    /// editor leaf alive but empty (issue #2283). The editor leaf we intend to\n    /// keep is made the active split so the synthesized placeholder buffer\n    /// lands there rather than in the dock, then the closing buffer is torn\n    /// down with `force_empty_placeholder` so no dock terminal gets adopted.\n    pub(crate) fn close_tab_keeping_editor_leaf_empty(\n        &mut self,","sourceCodeStart":26,"sourceCodeEnd":62,"githubUrl":"https://github.com/sinelaw/fresh/blob/67894ca5463dbd7a89bb31add4627c27d6b79d83/crates/fresh-editor/src/app/buffer_close.rs#L26-L62","documentation":"close_buffer refuses to close a buffer whose document has unsaved modifications. buffer_close.rs:44 checks state.buffer.is_modified() for the buffer in the active window and returns this error instead of discarding edits. It's a deliberate safety gate; close_buffer_internal (or force-close variants) bypass it.","triggerScenarios":"Calling close_buffer (directly or via close_tab_in_split, preview_file, dismiss_preview, handle_close_buffer, handle_close_terminal) while the target buffer's modified flag is set.","commonSituations":"User closes a tab with unsaved edits and no save-prompt path ran; scripted/automated tab cleanup hitting dirty buffers; preview close paths when the preview buffer was edited.","solutions":["Save the buffer first (or prompt the user to save/discard) before closing","Use the force-close API that skips the modified check when discarding edits is intended","Check buffer.is_modified() before calling close_buffer and branch to a save/discard dialog"],"exampleFix":"// before\neditor.close_buffer(id)?; // errors when dirty\n// after\nif editor.is_buffer_modified(id)? {\n    editor.save_buffer(id)?; // or prompt user\n}\neditor.close_buffer(id)?;","handlingStrategy":"validation","validationCode":"if editor.is_buffer_modified(id)? {\n    // prompt: Save / Discard / Cancel\n    prompt_save_before_close(id)?;\n}","typeGuard":null,"tryCatchPattern":"match editor.close_buffer(id) {\n    Err(e) if e.to_string() == \"Buffer has unsaved changes\" => {\n        editor.save_buffer(id)?;\n        editor.close_buffer(id)?;\n    }\n    other => other,\n}","preventionTips":["Check is_modified() before any programmatic close","Route user-facing closes through a save/discard prompt","Use force-close only when discarding is explicitly intended"],"tags":["editor","buffer","unsaved-changes","rust"],"backgroundTag":"invalid-state-transition","analyzedSha":"67894ca5463dbd7a89bb31add4627c27d6b79d83","analyzedAt":"2026-09-13T15:04:03.701Z","contentChangedAt":"2026-09-13T15:04:03.701Z","schemaVersion":2},"datasetVersion":"2026-09-16T04:17:20.429Z"}