sinelaw/fresh · error · io::Error (NotFound)

buffer not found

Error message

buffer not found

What it means

BufferMap::scan_leaf fails when a piece-tree leaf references a buffer_id that is absent from the buffers map. This is an internal consistency failure: leaves should never point at buffers that have been removed. It surfaces during byte-counting/scanning of leaf data.

Solutions

  1. Ensure leaves are invalidated/removed when their buffer is deleted from the map.
  2. Check the buffer_id is registered before scanning.
  3. Treat as an invariant violation and fix the ownership/lifecycle code that drops buffers with live leaves.
Defensive patterns

Strategy: try-catch

Validate before calling

// guard before scanning
if !buffers.contains_key(leaf.location.buffer_id()) {
    // leaf is stale; skip or rebuild
}

Try / catch

match map.scan_leaf(&leaf) {
    Ok(count) => count,
    Err(e) if e.to_string() == "buffer not found" => {
        // stale leaf: drop it and rescan
        0
    }
    Err(e) => return Err(e),
}

Prevention

When it happens

Trigger: Calling scan_leaf on a LeafData whose location.buffer_id() was never registered or was already removed from self.buffers (e.g. scanning after buffer close/eviction).

Common situations: Holding stale leaf references after closing a buffer; background scanning tasks racing with buffer removal.

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


AI-assisted analysis of sinelaw/fresh@67894ca546 (2026-09-13). Data as JSON: /api/errors/41ab077ec2130576. Report an issue: GitHub.

Appendix: source

Thrown at crates/fresh-editor-core/src/model/buffer/mod.rs:2157

            &**self.persistence.fs(),
            pattern,
            opts,
            &regex,
            max_matches,
            query_len,
        )
    }

    /// Count `\n` bytes in a single leaf.
    ///
    /// Uses `count_line_feeds_in_range` for unloaded buffers, which remote
    /// filesystem implementations can override to count server-side.
    pub fn scan_leaf(&self, leaf: &crate::model::piece_tree::LeafData) -> std::io::Result<usize> {
        let buffer_id = leaf.location.buffer_id();
        let buffer = self
            .buffers
            .get(buffer_id)
            .ok_or_else(|| std::io::Error::new(std::io::ErrorKind::NotFound, "buffer not found"))?;

        let count = match &buffer.data {
            crate::model::piece_tree::BufferData::Loaded { data, .. } => {
                let end = (leaf.offset + leaf.bytes).min(data.len());
                data[leaf.offset..end]
                    .iter()
                    .filter(|&&b| b == b'\n')
                    .count()
            }
            crate::model::piece_tree::BufferData::Unloaded {
                file_path,
                file_offset,
                ..
            } => {
                let read_offset = *file_offset as u64 + leaf.offset as u64;
                self.persistence.fs().count_line_feeds_in_range(
                    file_path,
                    read_offset,

View on GitHub (pinned to 67894ca546)