{"record":{"id":"f6fe6dde954026da","repo":"sinelaw/fresh","slug":"buffer-not-found-lsp-requests","errorCode":null,"errorMessage":"Buffer not found","messagePattern":"Buffer not found","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/fresh-editor/src/app/lsp_requests.rs","lineNumber":2632,"sourceCode":"                        .expect(\"active window must have a populated split layout\")\n                        .active_split()\n                });\n            self.windows\n                .get(&self.active_window)\n                .and_then(|w| w.buffers.splits())\n                .map(|(_, vs)| vs)\n                .expect(\"active window must have a populated split layout\")\n                .get(&split_id)\n                .map(|vs| vs.cursors.primary_id())\n                .unwrap_or_else(|| self.active_cursors().primary_id())\n        };\n\n        // Create events for all edits\n        for edit in edits {\n            let state = self\n                .buffers_mut()\n                .get_mut(&buffer_id)\n                .ok_or_else(|| io::Error::new(io::ErrorKind::NotFound, \"Buffer not found\"))?;\n\n            // Convert LSP range to byte positions\n            let start_line = edit.range.start.line as usize;\n            let start_char = edit.range.start.character as usize;\n            let end_line = edit.range.end.line as usize;\n            let end_char = edit.range.end.character as usize;\n\n            let start_pos = state.buffer.lsp_position_to_byte(start_line, start_char);\n            let end_pos = state.buffer.lsp_position_to_byte(end_line, end_char);\n            let buffer_len = state.buffer.len();\n\n            // Log the conversion for debugging\n            let old_text = if start_pos < end_pos && end_pos <= buffer_len {\n                state.get_text_range(start_pos, end_pos)\n            } else {\n                format!(\n                    \"<invalid range: start={}, end={}, buffer_len={}>\",\n                    start_pos, end_pos, buffer_len","sourceCodeStart":2614,"sourceCodeEnd":2650,"githubUrl":"https://github.com/sinelaw/fresh/blob/67894ca5463dbd7a89bb31add4627c27d6b79d83/crates/fresh-editor/src/app/lsp_requests.rs#L2614-L2650","documentation":"apply_lsp_text_edits maps LSP edits onto a specific buffer before applying them as a bulk edit. When the target buffer_id is not present in the app's buffer map (it was closed or the id is stale), it returns io::ErrorKind::NotFound 'Buffer not found' instead of silently skipping edits.","triggerScenarios":"Applying completion additional edits, formatting edits, workspace edits, or textDocument edits whose buffer was closed between the LSP request and the response; a server replying with edits for the wrong/unregistered buffer URI.","commonSituations":"User closes a file while a slow format-on-save or workspace-wide rename is in flight; LSP server sends edits for an unsaved/virtual buffer never opened by the client; stale buffer ids after restart of the language server.","solutions":["Look up the buffer by URI and re-open it if it was closed before applying edits","Check self.buffers().contains_key(&buffer_id) before requesting/applying edits","Drop or log the edits if the buffer no longer exists instead of failing the whole flow","Use IncrementalTextDocumentSync or re-request formatting after reopening"],"exampleFix":"// before\napp.apply_formatting_edits(buffer_id, edits)?; // NotFound if closed\n// after\nif app.buffer_exists(buffer_id) {\n    app.apply_formatting_edits(buffer_id, edits)?;\n} else {\n    log::info!(\"buffer {buffer_id} closed; discarding formatting edits\");\n}","handlingStrategy":"validation","validationCode":"fn can_apply(app: &App, buffer_id: BufferId) -> bool { app.buffers().contains_key(&buffer_id) }","typeGuard":null,"tryCatchPattern":"match app.apply_lsp_text_edits(buffer_id, edits) { Err(e) if e.kind() == io::ErrorKind::NotFound => log::info!(\"buffer gone; dropping edits\"), other => other?, }","preventionTips":["Cancel in-flight LSP requests when their buffer closes","Map buffer ids from URIs at apply time, not request time","Keep pending-edit queues keyed by URI so edits can be revalidated"],"tags":["lsp","buffer","not-found","race-condition"],"backgroundTag":"resource-not-found","analyzedSha":"67894ca5463dbd7a89bb31add4627c27d6b79d83","analyzedAt":"2026-09-13T15:04:03.701Z","contentChangedAt":"2026-09-13T15:04:03.701Z","schemaVersion":2},"datasetVersion":"2026-09-16T09:17:16.951Z"}