{"record":{"id":"552ffb1765987472","repo":"rust-lang/rust-analyzer","slug":"inconsistent-text-range","errorCode":null,"errorMessage":"inconsistent text range","messagePattern":"inconsistent text range","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/ide/src/rename.rs","lineNumber":105,"sourceCode":"        .filter(|(_, _, def, _, _)| def.range_for_rename(&sema).is_some())\n        .map(|(frange, kind, _, _, _)| {\n            always!(\n                frange.range.contains_inclusive(position.offset)\n                    && frange.file_id == position.file_id\n            );\n\n            Ok(match kind {\n                SyntaxKind::LIFETIME => {\n                    TextRange::new(frange.range.start() + TextSize::from(1), frange.range.end())\n                }\n                _ => frange.range,\n            })\n        })\n        .reduce(|acc, cur| match (acc, cur) {\n            // ensure all ranges are the same\n            (Ok(acc_inner), Ok(cur_inner)) if acc_inner == cur_inner => Ok(acc_inner),\n            (e @ Err(_), _) | (_, e @ Err(_)) => e,\n            _ => bail!(\"inconsistent text range\"),\n        });\n\n    match res {\n        // ensure at least one definition was found\n        Some(res) => res.map(|range| RangeInfo::new(range, ())),\n        None => bail!(\"No references found at position\"),\n    }\n}\n\n// Feature: Rename\n//\n// Renames the item below the cursor and all of its references\n//\n// | Editor  | Shortcut |\n// |---------|----------|\n// | VS Code | <kbd>F2</kbd> |\n//\n// ![Rename](https://user-images.githubusercontent.com/48062697/113065582-055aae80-91b1-11eb-8ade-2b58e6d81883.gif)","sourceCodeStart":87,"sourceCodeEnd":123,"githubUrl":"https://github.com/rust-lang/rust-analyzer/blob/e8f7e90aa3e7b26aa9a000200f606c1078da99ec/crates/ide/src/rename.rs#L87-L123","documentation":"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.","triggerScenarios":"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).","commonSituations":"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.","solutions":["Move the cursor precisely onto the identifier token (not adjacent punctuation or macro input) and retry prepare_rename.","Resolve the ambiguity in the source: avoid shadowed or macro-expanded bindings at that position.","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)."],"exampleFix":"// before (ambiguous: shadowed binding under cursor)\nlet x = 1; { macro_rules! m { () => { let x = 2; x } } m!(); }\n// after: disambiguate position or name\nlet x = 1; { let y = 2; y }\n","handlingStrategy":"validation","validationCode":"// Client-side: ensure the offset lands on an identifier character\nlet line_chars: Vec<char> = line.chars().collect();\nlet on_ident = offset_in_line <= line_chars.len()\n    && line_chars.get(offset_in_line.saturating_sub(1))\n        .map_or(false, |c| c.is_alphanumeric() || *c == '_' || *c == '\\'');\nif !on_ident { /* do not call prepare_rename */ }","typeGuard":"fn is_on_ident(line: &str, col: usize) -> bool {\n    line.chars().nth(col.saturating_sub(1))\n        .map_or(false, |c| c.is_alphanumeric() || c == '_' || c == '\\'')\n}","tryCatchPattern":"match prepare_rename(db, pos) {\n    Ok(range_info) => show_rename(range_info),\n    Err(e) if e.to_string().contains(\"inconsistent text range\") => {\n        fallback_to_find_references(pos); // ambiguous target\n    }\n    Err(e) => report(e),\n}","preventionTips":["Only invoke rename/prepare_rename with the cursor directly on an identifier token","Avoid renaming inside macro-generated or desugared spans","Sync document content with the server before sending rename requests","Treat rename failures as non-fatal and fall back to search-and-replace"],"tags":["rust-analyzer","rename","lsp","ambiguity"],"backgroundTag":"rename-target-ambiguous","analyzedSha":"e8f7e90aa3e7b26aa9a000200f606c1078da99ec","analyzedAt":"2026-09-03T21:08:06.959Z","contentChangedAt":"2026-09-03T21:08:06.959Z","schemaVersion":2},"datasetVersion":"2026-09-11T07:07:21.782Z"}