rust-lang/rust-analyzer · error

inconsistent text range

Error message

inconsistent text range

What it means

During prepare_rename, rust-analyzer collects every candidate definition found at the cursor position and requires all of them to resolve to the exact same text range, since a single rename target must be produced. When two or more overlapping definitions at the offset map to different ranges, the reduce step cannot pick one and bails with this error. It indicates an ambiguity in resolution at that position that the rename feature cannot handle.

Source

Thrown at crates/ide/src/rename.rs:105

        .filter(|(_, _, def, _, _)| def.range_for_rename(&sema).is_some())
        .map(|(frange, kind, _, _, _)| {
            always!(
                frange.range.contains_inclusive(position.offset)
                    && frange.file_id == position.file_id
            );

            Ok(match kind {
                SyntaxKind::LIFETIME => {
                    TextRange::new(frange.range.start() + TextSize::from(1), frange.range.end())
                }
                _ => frange.range,
            })
        })
        .reduce(|acc, cur| match (acc, cur) {
            // ensure all ranges are the same
            (Ok(acc_inner), Ok(cur_inner)) if acc_inner == cur_inner => Ok(acc_inner),
            (e @ Err(_), _) | (_, e @ Err(_)) => e,
            _ => bail!("inconsistent text range"),
        });

    match res {
        // ensure at least one definition was found
        Some(res) => res.map(|range| RangeInfo::new(range, ())),
        None => bail!("No references found at position"),
    }
}

// Feature: Rename
//
// Renames the item below the cursor and all of its references
//
// | Editor  | Shortcut |
// |---------|----------|
// | VS Code | <kbd>F2</kbd> |
//
// ![Rename](https://user-images.githubusercontent.com/48062697/113065582-055aae80-91b1-11eb-8ade-2b58e6d81883.gif)

View on GitHub (pinned to e8f7e90aa3)

Solutions

  1. Move the cursor precisely onto the identifier token (not adjacent punctuation or macro input) and retry prepare_rename.
  2. Resolve the ambiguity in the source: avoid shadowed or macro-expanded bindings at that position.
  3. If this is a rust-analyzer bug, reproduce with a minimal fixture and report; meanwhile rely on the editor's fallback (find references + manual rename).

Example fix

// before (ambiguous: shadowed binding under cursor)
let x = 1; { macro_rules! m { () => { let x = 2; x } } m!(); }
// after: disambiguate position or name
let x = 1; { let y = 2; y }
Defensive patterns

Strategy: validation

Validate before calling

// Client-side: ensure the offset lands on an identifier character
let line_chars: Vec<char> = line.chars().collect();
let on_ident = offset_in_line <= line_chars.len()
    && line_chars.get(offset_in_line.saturating_sub(1))
        .map_or(false, |c| c.is_alphanumeric() || *c == '_' || *c == '\'');
if !on_ident { /* do not call prepare_rename */ }

Type guard

fn is_on_ident(line: &str, col: usize) -> bool {
    line.chars().nth(col.saturating_sub(1))
        .map_or(false, |c| c.is_alphanumeric() || c == '_' || c == '\'')
}

Try / catch

match prepare_rename(db, pos) {
    Ok(range_info) => show_rename(range_info),
    Err(e) if e.to_string().contains("inconsistent text range") => {
        fallback_to_find_references(pos); // ambiguous target
    }
    Err(e) => report(e),
}

Prevention

When it happens

Trigger: Calling prepare_rename (via the textDocument/rename prepare LSP request) at a cursor offset where find_definitions yields multiple definitions whose range_for_rename differs — e.g. positions where name classification is ambiguous (macro-expanded names, overlapping shadowed bindings, or attribute/macro-generated tokens resolving to distinct defs).

Common situations: Renaming an identifier that sits inside macro-generated or desugared code where the same token resolves to several defs; IDE plugin requests at ambiguous positions in edition-ambiguous files; typically hit by editor users pressing F2 on tricky code rather than by library consumers directly.

Related errors


AI-assisted analysis of rust-lang/rust-analyzer@e8f7e90aa3 (2026-09-03). Data as JSON: /api/errors/552ffb1765987472. Report an issue: GitHub.