zed-industries/zed · error

anchor's path was never added to multibuffer

Error message

anchor's path was never added to multibuffer

What it means

MultiBuffer anchors store a path key index into the snapshot's path_keys set, assigned when the anchor's buffer is added. When two anchors are compared (Anchor::cmp, used by sorting and cursor seeking), each anchor's path index is looked up in the snapshot; this panic (line 107) fires when the first anchor's index is absent - meaning the anchor does not belong to this snapshot. Usually it is a stale anchor whose buffer/path was removed after the snapshot was taken, or an anchor from a different multibuffer.

Source

Thrown at crates/multi_buffer/src/anchor.rs:107

}

impl ExcerptAnchor {
    pub(crate) fn buffer_id(&self) -> BufferId {
        self.text_anchor.buffer_id
    }

    pub(crate) fn text_anchor(&self) -> text::Anchor {
        self.text_anchor
    }

    pub(crate) fn with_diff_base_anchor(mut self, diff_base_anchor: text::Anchor) -> Self {
        self.diff_base_anchor = Some(diff_base_anchor);
        self
    }

    pub(crate) fn cmp(&self, other: &Self, snapshot: &MultiBufferSnapshot) -> Ordering {
        let Some(self_path_key) = snapshot.path_keys.get_index(self.path.0 as usize) else {
            panic!("anchor's path was never added to multibuffer")
        };
        let Some(other_path_key) = snapshot.path_keys.get_index(other.path.0 as usize) else {
            panic!("anchor's path was never added to multibuffer")
        };

        match self_path_key.cmp(other_path_key) {
            Ordering::Equal => (),
            ordering => return ordering,
        }

        // in the case that you removed the buffer containing self,
        // and added the buffer containing other with the same path key
        // (ordering is arbitrary but consistent)
        if self.text_anchor.buffer_id != other.text_anchor.buffer_id {
            return self.text_anchor.buffer_id.cmp(&other.text_anchor.buffer_id);
        }

        // two anchors into the same buffer at the same path

View on GitHub (pinned to f4178619ac)

Solutions

  1. Take a fresh multibuffer.snapshot(cx) after any buffer removal and re-create/refresh anchors from it before comparing
  2. Drop or recreate anchors whose buffer no longer exists in the snapshot (check buffer_id membership) instead of comparing them
  3. Ensure anchors are only ever compared within the multibuffer instance that created them
  4. If you control the call path, validate the path index and skip/log instead of panicking

Example fix

// before: anchors from an older snapshot get sorted
anchors.sort_by(|a, b| a.cmp(b, &old_snapshot)); // panics if a buffer was removed

// after: refresh the snapshot and keep only live anchors
let snapshot = multi_buffer.read(cx).snapshot(cx);
let live: Vec<_> = anchors
    .into_iter()
    .filter(|anchor| snapshot.buffer_ids().contains(&anchor.buffer_id))
    .collect();
live.sort_by(|a, b| a.cmp(b, &snapshot));
Defensive patterns

Strategy: validation

Validate before calling

// discard anchors that no longer resolve in this snapshot before comparing
fn anchor_is_live(anchor: &Anchor, snapshot: &MultiBufferSnapshot) -> bool {
    snapshot.buffer_ids().contains(&anchor.buffer_id)
}

Type guard

fn live_anchors(
    anchors: impl IntoIterator<Item = Anchor>,
    snapshot: &MultiBufferSnapshot,
) -> Vec<Anchor> {
    anchors
        .into_iter()
        .filter(|anchor| snapshot.buffer_ids().contains(&anchor.buffer_id))
        .collect()
}

Prevention

When it happens

Trigger: Sorting or seeking with anchors against a MultiBufferSnapshot whose path_keys no longer contains the anchor's index: the buffer was removed (project search cleared results, a file was closed) while anchors created before the removal are still compared, or anchors from another multibuffer instance are mixed in.

Common situations: Project-wide search replacing all buffers at once while cursors/selections still hold old anchors; multibuffers containing several buffers that share a path; reusing cached snapshots after edits that remove excerpts; tests that build anchors against snapshot A and compare them via snapshot B.

Related errors


AI-assisted analysis of zed-industries/zed@f4178619ac (2026-08-20). Data as JSON: /api/errors/d1b5a809f5ccaca1. Report an issue: GitHub.