sinelaw/fresh · error
Buffer not found
Error message
Buffer not found
What it means
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.
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
Example fix
// before
app.apply_formatting_edits(buffer_id, edits)?; // NotFound if closed
// after
if app.buffer_exists(buffer_id) {
app.apply_formatting_edits(buffer_id, edits)?;
} else {
log::info!("buffer {buffer_id} closed; discarding formatting edits");
} Defensive patterns
Strategy: validation
Validate before calling
fn can_apply(app: &App, buffer_id: BufferId) -> bool { app.buffers().contains_key(&buffer_id) } Try / catch
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?, } Prevention
- 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
When it happens
Trigger: 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.
Common situations: 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.
Understand the failure class
Background: 'Could not be found', 'does not exist', 'not found in database': the resource-not-found family when an ID, slug, key, or URI lookup comes back empty — this error's family across 20 libraries.
Related errors
- workspace is still being created and cannot be
- no such folder
- no such folder
- No file path associated with buffer
- Failed to read data at offset
AI-assisted analysis of sinelaw/fresh@67894ca546 (2026-09-13).
Data as JSON: /api/errors/f6fe6dde954026da.
Report an issue: GitHub.
Appendix: source
Thrown at crates/fresh-editor/src/app/lsp_requests.rs:2632
.expect("active window must have a populated split layout")
.active_split()
});
self.windows
.get(&self.active_window)
.and_then(|w| w.buffers.splits())
.map(|(_, vs)| vs)
.expect("active window must have a populated split layout")
.get(&split_id)
.map(|vs| vs.cursors.primary_id())
.unwrap_or_else(|| self.active_cursors().primary_id())
};
// Create events for all edits
for edit in edits {
let state = self
.buffers_mut()
.get_mut(&buffer_id)
.ok_or_else(|| io::Error::new(io::ErrorKind::NotFound, "Buffer not found"))?;
// Convert LSP range to byte positions
let start_line = edit.range.start.line as usize;
let start_char = edit.range.start.character as usize;
let end_line = edit.range.end.line as usize;
let end_char = edit.range.end.character as usize;
let start_pos = state.buffer.lsp_position_to_byte(start_line, start_char);
let end_pos = state.buffer.lsp_position_to_byte(end_line, end_char);
let buffer_len = state.buffer.len();
// Log the conversion for debugging
let old_text = if start_pos < end_pos && end_pos <= buffer_len {
state.get_text_range(start_pos, end_pos)
} else {
format!(
"<invalid range: start={}, end={}, buffer_len={}>",
start_pos, end_pos, buffer_lenView on GitHub (pinned to 67894ca546)