{"record":{"id":"14d0a0115346a9b3","repo":"sinelaw/fresh","slug":"buffer-range-out-of-bounds-requested-buffer-size","errorCode":null,"errorMessage":"Buffer range out of bounds: requested {}..{}, buffer size {}","messagePattern":"Buffer range out of bounds: requested (.+?)\\.\\.(.+?), buffer size (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/fresh-editor-core/src/model/buffer/mod.rs","lineNumber":1411,"sourceCode":"\n                // Clip to the requested range\n                let read_start = current_offset.max(piece_start_in_doc);\n                let read_end = end_offset.min(piece_end_in_doc);\n\n                if read_end > read_start {\n                    let offset_in_piece = read_start - piece_start_in_doc;\n                    let bytes_to_read = read_end - read_start;\n\n                    let buffer_start = piece_view.buffer_offset + offset_in_piece;\n                    let buffer_end = buffer_start + bytes_to_read;\n\n                    // Buffer should be loaded now\n                    let buffer = self.buffers.get(buffer_id).context(\"Buffer not found\")?;\n                    let data = buffer\n                        .get_data()\n                        .context(\"Buffer data unavailable after load\")?;\n\n                    anyhow::ensure!(\n                        buffer_end <= data.len(),\n                        \"Buffer range out of bounds: requested {}..{}, buffer size {}\",\n                        buffer_start,\n                        buffer_end,\n                        data.len()\n                    );\n\n                    result.extend_from_slice(&data[buffer_start..buffer_end]);\n                    current_offset = read_end;\n                    made_progress = true;\n                }\n            }\n\n            // If we didn't make progress and didn't restart iteration, this is an error\n            if !made_progress && !restarted_iteration {\n                tracing::error!(\n                    \"get_text_range_mut: No progress at offset {} (requested range: {}..{}, buffer len: {})\",\n                    current_offset,","sourceCodeStart":1393,"sourceCodeEnd":1429,"githubUrl":"https://github.com/sinelaw/fresh/blob/67894ca5463dbd7a89bb31add4627c27d6b79d83/crates/fresh-editor-core/src/model/buffer/mod.rs#L1393-L1429","documentation":"A buffered range read verified with anyhow::ensure! that buffer_end <= data.len() failed: the requested byte range extends past the end of the buffer's data. buffer/mod.rs:1411 guards after waiting for the buffer to load and fetching its data, so this indicates a stale/oversized range versus actual buffer content.","triggerScenarios":"Requesting buffer content for a range (buffer_start..buffer_end) computed against an older buffer length, then the file shrank (external modification, truncated reload) — or a caller passing an end offset beyond the buffer size.","commonSituations":"File changed on disk and shrank while the editor held old offsets; rendering code caching buffer lengths across reloads; plugins using stale spans after a revert/reload.","solutions":["Re-fetch the current buffer length and clamp buffer_end to data.len() before requesting the range","Invalidate cached offsets/ranges after any reload or external file change","Refresh the buffer from disk (reload) before reading ranges if the file may have changed externally"],"exampleFix":"// before\nlet data = read_buffer_range(buffer_id, 0, cached_len)?;\n// after\nlet len = current_buffer_len(buffer_id)?;\nlet data = read_buffer_range(buffer_id, 0, cached_len.min(len))?;","handlingStrategy":"validation","validationCode":"let len = current_buffer_len(buffer_id)?;\nlet end = end.min(len);\nif start > end { return Ok(String::new()); }","typeGuard":null,"tryCatchPattern":"match read_buffer_range(buffer_id, s, e) {\n    Err(e) if e.to_string().contains(\"out of bounds\") => reload_and_recompute_ranges(buffer_id),\n    other => other,\n}","preventionTips":["Re-read buffer length immediately before range reads; never cache lengths across reloads","Clamp ranges to data.len() before requesting","Invalidate cached spans when the file changes on disk"],"tags":["editor","buffer","out-of-bounds","rust"],"backgroundTag":"index-out-of-bounds","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"}