sinelaw/fresh · critical
Failed to read data at offset
Error message
Failed to read data at offset {}: no progress made (requested {}..{}, buffer len: {}) What it means
The piece-tree buffer's read path walks chunks to satisfy a byte-range read. If an iteration over the piece tree makes no forward progress (current_offset doesn't advance toward end_offset), an internal invariant has been broken — continuing would loop forever — so the code logs piece-tree stats and bails with 'Failed to read data at offset ...: no progress made'. This indicates a corrupted piece tree or a bug, not bad user input.
Solutions
- Report/inspect as a bug: capture the logged piece-tree stats (len, total_bytes) and the offset range from the message.
- Reload the buffer from disk (re-open the file) to rebuild a clean piece tree.
- Verify callers pass offsets derived from the buffer's current len() and refresh cached offsets after edits.
- If reproducible, reduce to a minimal edit/undo sequence and file an issue with the reproduction steps.
Example fix
// before: stale offset cached before a deletion let off = buffer.len(); buffer.delete(...); buffer.read_data(off..off + n)?; // no-progress bail // after: clamp to the current length at read time let off = off.min(buffer.len()); let end = (off + n).min(buffer.len()); buffer.read_data(off..end)?;
Defensive patterns
Strategy: validation
Validate before calling
// Rust: clamp read ranges to the buffer's current length
let off = offset.min(buffer.len());
let end = end_offset.min(buffer.len());
if off >= end { return Ok(Vec::new()); } Try / catch
match buffer.read_data(range) {
Err(e) if e.to_string().contains("no progress made") => {
tracing::error!("piece tree invariant violation: {e}");
// recover by reloading the buffer from disk
buffer = Buffer::load_file(path)?;
}
other => other?,
} Prevention
- Never cache byte offsets across edits; re-read len() before each range read.
- Treat this error as a bug report trigger — capture the logged piece-tree stats.
- Reload the buffer from disk after encountering it; the piece tree may be corrupted.
When it happens
Trigger: Requesting read_data (or a bulk read spanning ranges) at an offset/end range when the chunk walk fails to advance current_offset — typically a piece-tree invariant violation: stale piece references after edits, an offset beyond current length slipping past earlier checks, or a deletion/undo that left empty/zero-length pieces in the walk.
Common situations: After complex undo/redo or concurrent edit sequences that corrupt piece ordering; extension/API code caching offsets and reading after the buffer shrank; genuinely a library bug — users rarely trigger it intentionally.
Understand the failure class
Background: "This is a bug, please report it": internal invariant violations, unreachable panics, and SNH errors explained — this error's family across 47 libraries.
Related errors
- No file path associated with buffer
- Cannot reload: buffer has unsaved modifications
- Buffer range out of bounds: requested
- Buffer has unsaved changes
- Buffer has no file path
AI-assisted analysis of sinelaw/fresh@67894ca546 (2026-09-13).
Data as JSON: /api/errors/022a4cd1a9dc69fc.
Report an issue: GitHub.
Appendix: source
Thrown at crates/fresh-editor-core/src/model/buffer/mod.rs:1438
current_offset = read_end;
made_progress = true;
}
}
// If we didn't make progress and didn't restart iteration, this is an error
if !made_progress && !restarted_iteration {
tracing::error!(
"get_text_range_mut: No progress at offset {} (requested range: {}..{}, buffer len: {})",
current_offset,
offset,
end_offset,
self.len()
);
tracing::error!(
"Piece tree stats: {} total bytes",
self.piece_tree.stats().total_bytes
);
anyhow::bail!(
"Failed to read data at offset {}: no progress made (requested {}..{}, buffer len: {})",
current_offset,
offset,
end_offset,
self.len()
);
}
}
if iteration_count > 1 {
tracing::info!(
iteration_count,
result_len = result.len(),
"get_text_range_mut: completed with multiple iterations"
);
}
crate::counters::work::add_buffer_bytes_read(result.len() as u64);View on GitHub (pinned to 67894ca546)