{"record":{"id":"4a4b938b32306d9e","repo":"rust-lang/rust-analyzer","slug":"no-file-available-to-rename","errorCode":null,"errorMessage":"No file available to rename","messagePattern":"No file available to rename","errorType":"error_code","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/ide-db/src/rename.rs","lineNumber":790,"sourceCode":"                            new_name.display(sema.db, source.file_id.edition(sema.db)).to_string(),\n                        );\n                    }\n                } else {\n                    edit.replace(\n                        name_range,\n                        new_name.display(sema.db, source.file_id.edition(sema.db)).to_string(),\n                    );\n                }\n            }\n        }\n        let mut edit = edit.finish();\n\n        for (edit, _) in source_change.source_file_edits.values_mut() {\n            edit.set_annotation(conflict_annotation);\n        }\n        edit.set_annotation(conflict_annotation);\n\n        let Some(file_id) = file_id else { bail!(\"No file available to rename\") };\n        return Ok((file_id.file_id(sema.db), edit));\n    }\n    let FileRange { file_id, range } = def\n        .range_for_rename(sema)\n        .ok_or_else(|| format_err!(\"No identifier available to rename\"))?;\n    let (range, new_name) = match def {\n        Definition::ExternCrateDecl(decl) if decl.alias(sema.db).is_none() => (\n            TextRange::empty(range.end()),\n            format!(\" as {}\", new_name.display(sema.db, file_id.edition(sema.db)),),\n        ),\n        _ => (range, new_name.display(sema.db, file_id.edition(sema.db)).to_string()),\n    };\n    edit.replace(range, new_name);\n    Ok((file_id.file_id(sema.db), edit.finish()))\n}\n\n#[derive(Copy, Clone, Debug, PartialEq)]\npub enum IdentifierKind {","sourceCodeStart":772,"sourceCodeEnd":808,"githubUrl":"https://github.com/rust-lang/rust-analyzer/blob/e8f7e90aa3e7b26aa9a000200f606c1078da99ec/crates/ide-db/src/rename.rs#L772-L808","documentation":"rust-analyzer's rename implementation (`source_edit_from_def` in crates/ide-db/src/rename.rs) builds text edits for every occurrence of the definition, tracking which file each occurrence lives in. This bail fires when, after collecting all edits, no file id was ever recorded (the local `file_id` Option stayed None), so there is no file on which to anchor the rename. It means the definition's textual source could not be resolved to a concrete file, typically because the definition comes from a macro or generated code whose origin file is unavailable.","triggerScenarios":"Calling the rename request (textDocument/rename) on a definition whose source is produced inside a macro declaration or expansion such that no `FileRange` for the identifier can be obtained; `rename_reference` -> `source_edit_from_def` runs with `file_id == None` at crates/ide-db/src/rename.rs:790. Related sibling error: `range_for_rename` returning None yields 'No identifier available to rename'.","commonSituations":"Renaming a local variable or binding introduced by a declarative macro (macro_rules!) whose defining site is in a macro body rust-analyzer cannot map back to a file; renaming symbols in heavily macro-generated code; renaming when the definition comes from a desugared/anonymous binding.","solutions":["Rename the symbol at its real (non-macro) definition site instead of the expanded/macro-introduced occurrence.","Manually edit the macro definition text where the binding is declared, then rebuild.","If the symbol genuinely has no file-anchored source, the rename is unsupported — do not attempt it; fall back to textual search-and-replace.","Check for a rust-analyzer update; macro-defile mapping support improves between versions."],"exampleFix":"// before: rename invoked on a local bound inside a macro body\nmacro_rules! m { () => { let tmp = 1; tmp } }\nm!(); // cursor on `tmp` -> rename fails\n\n// after: rename the identifier in the macro definition itself\nmacro_rules! m { () => { let value = 1; value } }","handlingStrategy":"try-catch","validationCode":"// Client-side: only send rename for symbols whose definition is plain code.\n// Heuristic check on the symbol under the cursor before calling rename:\nfn is_plain_definition(def: &lsp_types::DocumentSymbol) -> bool {\n    // skip symbols inside macro expansions / generated ranges\n    !def.name.starts_with(\"macro\")\n}","typeGuard":"fn is_renameable(def_name: &str, kind_supported: bool) -> bool {\n    kind_supported && !def_name.is_empty()\n}","tryCatchPattern":"// Wrap the LSP rename request and surface a friendly message.\nmatch rename(symbol, new_name) {\n    Ok(edit) => apply_workspace_edit(edit),\n    Err(e) if e.to_string().contains(\"No file available to rename\") => {\n        notify(\"Cannot rename: symbol is defined inside a macro; edit the macro definition manually.\");\n    }\n    Err(e) => notify(&format!(\"Rename failed: {e}\")),\n}","preventionTips":["Avoid renaming symbols introduced inside macro_rules! bodies; edit the macro instead.","Prefer renaming at the original definition site, not an expanded occurrence.","Keep rust-analyzer updated for better macro def-map support.","Fall back to project-wide textual search/replace for macro-bound names."],"tags":["rust-analyzer","rename","macros","lsp"],"backgroundTag":"rename-target-unresolvable","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"}