{"record":{"id":"63b5f9d62e2fa0ae","repo":"sxyazi/yazi","slug":"failed-to-retrieve-file-info-63b5f9","errorCode":null,"errorMessage":"Failed to retrieve file info","messagePattern":"Failed to retrieve file info","errorType":"exception","errorClass":"anyhow::Error","httpStatus":null,"severity":"warning","filePath":"yazi-actor/src/mgr/bulk_rename.rs","lineNumber":132,"sourceCode":"\n\t\tlet permit = WATCHER.acquire().await.unwrap();\n\t\tlet (mut failed, mut succeeded) = (Vec::new(), HashMap::with_capacity(todo.len()));\n\t\tfor (o, n) in todo {\n\t\t\tlet (Ok(old), Ok(new)) =\n\t\t\t\t(Self::replace_url(&selected[o.0], root, &o), Self::replace_url(&selected[n.0], root, &n))\n\t\t\telse {\n\t\t\t\tfailed.push((o, n, anyhow!(\"Invalid new or old file name\")));\n\t\t\t\tcontinue;\n\t\t\t};\n\n\t\t\tif maybe_exists(&new).await && !engine::must_identical(&old, &new).await {\n\t\t\t\tfailed.push((o, n, anyhow!(\"Destination already exists\")));\n\t\t\t} else if let Err(e) = engine::rename(&old, &new).await {\n\t\t\t\tfailed.push((o, n, e.into()));\n\t\t\t} else if let Ok(f) = engine::file(new).await {\n\t\t\t\tsucceeded.insert(old, f);\n\t\t\t} else {\n\t\t\t\tfailed.push((o, n, anyhow!(\"Failed to retrieve file info\")));\n\t\t\t}\n\t\t}\n\n\t\tif !succeeded.is_empty() {\n\t\t\tlet it = succeeded.iter().map(|(o, n)| (o.as_url(), n.url.as_url()));\n\t\t\tlog_if_err!(Pubsub::pub_after_bulk_rename(it));\n\t\t\tFilesOp::rename(succeeded);\n\t\t}\n\t\tdrop(permit);\n\n\t\tif !failed.is_empty() {\n\t\t\tSelf::output_failed(failed).await?;\n\t\t}\n\t\tOk(())\n\t}\n\n\tfn opener() -> Option<OpenerRuleArc> {\n\t\tYAZI","sourceCodeStart":114,"sourceCodeEnd":150,"githubUrl":"https://github.com/sxyazi/yazi/blob/94abcfa92f4ad3f0a1aef6c1ea083cfb8aa6c8c2/yazi-actor/src/mgr/bulk_rename.rs#L114-L150","documentation":"After engine::rename succeeds for a pair, bulk rename stats the new path with engine::file(new) to build the File handed to FilesOp::rename. If that stat fails the pair is recorded as failed with \"Failed to retrieve file info\" — although the rename already happened on disk. The in-memory listing is simply not updated for that pair.","triggerScenarios":"Rename succeeds but the follow-up metadata read fails: remote/archive backends with lagging metadata, the renamed file being moved/deleted immediately after by a watcher or concurrent process, or permission changes on the destination directory.","commonSituations":"Bulk renaming on network mounts or inside archives; running while file watchers/sync clients react to each rename and touch the files again.","solutions":["Verify on disk — the rename most likely already applied; refresh the directory listing","Retry the stat once after a short delay on remote/archive backends","Suspend sync clients and watchers during large bulk renames"],"exampleFix":null,"handlingStrategy":"retry","validationCode":null,"typeGuard":null,"tryCatchPattern":"// Rename already succeeded; retry only the stat before declaring failure.\n} else if let Ok(f) = engine::file(&new).await {\n    succeeded.insert(old, f);\n} else if let Ok(f) = tokio::time::sleep(std::time::Duration::from_millis(200)).await,\n    engine::file(&new).await\n{\n    succeeded.insert(old, f);\n} else {\n    failed.push((o, n, anyhow!(\"Failed to retrieve file info\")));\n}","preventionTips":["Treat 'Failed to retrieve file info' after rename as a soft failure; verify on disk","Retry the stat once on remote/archive backends","Suspend watchers/sync clients during large bulk renames"],"tags":["bulk-rename","vfs","metadata","race-condition"],"backgroundTag":null,"analyzedSha":"94abcfa92f4ad3f0a1aef6c1ea083cfb8aa6c8c2","analyzedAt":"2026-08-16T09:56:24.836Z","schemaVersion":2},"datasetVersion":"2026-08-16T13:17:31.715Z"}