zed-industries/zed · error

Edit index {i} has been already used. Perhaps your spec cont

Error message

Edit index {i} has been already used. Perhaps your spec contains duplicates

What it means

reorder_edits remaps original edit indexes as edits are extracted, marking consumed indexes as None in indexes_map. Each round filters out already-used indexes before collecting, so the unwrap guard fires only when an edit index is referenced again after being consumed — the message attributes this to duplicate edit indexes in the spec (edits_order / the example's expected-patch ordering referencing the same edit twice). In practice the preceding filter makes this nearly unreachable; hitting it means the ordering spec hit an edge the filter did not cover or internal state is inconsistent.

Source

Thrown at crates/edit_prediction_cli/src/reorder_patch.rs:87

    let stats = patch.stats();
    let total_edits = stats.added + stats.removed;
    let mut indexes_map = BTreeMap::from_iter((0..total_edits).map(|i| (i, Some(i))));

    for patch_edits_order in edits_order {
        // Skip duplicated indexes that were already processed
        let patch_edits_order = patch_edits_order
            .into_iter()
            .filter(|&i| indexes_map[&i].is_some()) // skip duplicated indexes
            .collect::<BTreeSet<_>>();

        if patch_edits_order.is_empty() {
            continue;
        }

        let order = patch_edits_order
            .iter()
            .map(|&i| {
                indexes_map[&i].unwrap_or_else(|| panic!("Edit index {i} has been already used. Perhaps your spec contains duplicates"))
            })
            .collect::<BTreeSet<_>>();

        let extracted;
        (extracted, remainder) = extract_edits(&remainder, &order);

        result.hunks.extend(extracted.hunks);

        // Update indexes_map to reflect applied edits. For example:
        //
        // Original_index | Removed?  | Mapped_value
        //       0        | false     | 0
        //       1        | true      | None
        //       2        | true      | None
        //       3        | false     | 1

        for index in patch_edits_order {
            indexes_map.insert(index, None);

View on GitHub (pinned to f4178619ac)

Solutions

  1. Dedupe edit indexes in the spec's ordering so each edit is referenced exactly once
  2. Verify all indexes are within 0..(added+removed) of the patch being reordered
  3. If a minimal spec still triggers it, the guard is firing on an internal invariant bug in reorder_patch — report it with the patch and order spec

Example fix

// before
let order = vec![BTreeSet::from([0, 1]), BTreeSet::from([1, 2])]; // index 1 twice

// after
let order = vec![BTreeSet::from([0, 1]), BTreeSet::from([2])];
Defensive patterns

Strategy: validation

Validate before calling

// ensure each edit index is referenced exactly once across rounds
let mut seen = std::collections::BTreeSet::new();
for round in &edits_order {
    for &i in round {
        assert!(seen.insert(i), "duplicate edit index {i} in spec");
    }
}

Type guard

fn has_unique_edit_indexes(order: &[BTreeSet<usize>]) -> bool {
    let mut seen = std::collections::BTreeSet::new();
    order.iter().all(|r| r.iter().all(|i| seen.insert(*i)))
}

Prevention

When it happens

Trigger: An example spec whose edit ordering references the same edit index multiple times across rounds, or indexes outside 0..total_edits corrupting indexes_map state; typically hand-edited or synthesized specs with duplicated edit indexes.

Common situations: Hand-written example markdown/json where the same edit appears in two events; a generator bug emitting duplicate indexes in edits_order.

Related errors


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