{"record":{"id":"5e6b63966a201ae2","repo":"rust-lang/rust-analyzer","slug":"no-files-to-search","errorCode":null,"errorMessage":"No files to search","messagePattern":"No files to search","errorType":"error_code","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/ide-ssr/src/lib.rs","lineNumber":156,"sourceCode":"        .ok_or_else(|| SsrError(\"no resolution scope for file\".into()))?;\n        Ok(MatchFinder { sema, rules: Vec::new(), resolution_scope, restrict_ranges })\n    }\n\n    /// Constructs an instance using the start of the first file in `db` as the lookup context.\n    pub fn at_first_file(db: &'db ide_db::RootDatabase) -> Result<MatchFinder<'db>, SsrError> {\n        if let Some(first_file_id) = LocalRoots::get(db)\n            .roots(db)\n            .iter()\n            .next()\n            .and_then(|root| db.source_root(*root).source_root(db).iter().next())\n        {\n            MatchFinder::in_context(\n                db,\n                ide_db::FilePosition { file_id: first_file_id, offset: 0.into() },\n                vec![],\n            )\n        } else {\n            bail!(\"No files to search\");\n        }\n    }\n\n    /// Adds a rule to be applied. The order in which rules are added matters. Earlier rules take\n    /// precedence. If a node is matched by an earlier rule, then later rules won't be permitted to\n    /// match to it.\n    pub fn add_rule(&mut self, rule: SsrRule) -> Result<(), SsrError> {\n        for parsed_rule in rule.parsed_rules {\n            self.rules.push(ResolvedRule::new(\n                parsed_rule,\n                &self.resolution_scope,\n                self.rules.len(),\n            )?);\n        }\n        Ok(())\n    }\n\n    /// Finds matches for all added rules and returns edits for all found matches.","sourceCodeStart":138,"sourceCodeEnd":174,"githubUrl":"https://github.com/rust-lang/rust-analyzer/blob/e8f7e90aa3e7b26aa9a000200f606c1078da99ec/crates/ide-ssr/src/lib.rs#L138-L174","documentation":"ide-ssr's `at_first_file` entry point requires at least one file to operate on: it picks the first file, creates a MatchFinder rooted at that file position, and only then applies SSR rules. When the supplied file list (or the resolution of the requested file) yields no file id, the library cannot anchor the search anywhere, so it fails fast with `bail!(\"No files to search\")`.","triggerScenarios":"Calling `SsrPattern/MatchFinder::at_first_file` (or the ide-ssr API backed by it, e.g. structural search/replace via `ide_db` handlers) with an empty file-id vector, or with input whose file resolution produced no valid `FileId` (e.g. an unopened/nonexistent file filtered out upstream).","commonSituations":"Batch refactoring scripts driven over a VFS snapshot where no files were loaded yet; editors invoking SSR before the workspace finished loading; callers passing a path that failed to resolve to a FileId so the resulting collection is empty.","solutions":["Ensure at least one file is resolved to a valid `FileId` before calling the SSR entry point.","Check the file collection for emptiness and bail early in your own code with a clearer message (e.g. 'open a file first').","If files should exist, verify the VFS/load path: the file may not be added to the database yet.","Fall back to the multi-file API (`MatchFinder::in_context` with your own file list) only after confirming it is non-empty."],"exampleFix":"// before\nlet ssr = SsrPattern::at_first_file(db, /* files possibly empty */)?;\n// after\nanyhow::ensure!(!file_ids.is_empty(), \"SSR requires at least one open file\");\nlet ssr = SsrPattern::at_first_file(db, file_ids)?;","handlingStrategy":"validation","validationCode":"// caller-side pre-check before invoking SSR\nif file_ids.is_empty() {\n    return Err(anyhow::anyhow!(\"SSR needs at least one resolved file; got none\"));\n}\nlet ssr = SsrPattern::at_first_file(db, file_ids)?;","typeGuard":"fn has_files(files: &[FileId]) -> bool { !files.is_empty() }","tryCatchPattern":"match SsrPattern::at_first_file(db, file_ids) {\n    Ok(s) => s,\n    Err(e) if e.to_string().contains(\"No files to search\") => {\n        eprintln!(\"No files loaded for SSR; open/resolve a file first\");\n        return Ok(());\n    }\n    Err(e) => return Err(e.into()),\n}","preventionTips":["Resolve file paths to FileIds and assert the list is non-empty before SSR","Confirm the VFS/workspace has finished loading before running batch search/replace","Handle 'nothing loaded' states in the UI/CLI instead of passing empty collections downstream"],"tags":["rust","ide-ssr","empty-input","structural-search"],"backgroundTag":"empty-input-set","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"}