{"record":{"id":"2dd698dab102dba1","repo":"sxyazi/yazi","slug":"failed-to-retrieve-file-info","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_create.rs","lineNumber":92,"sourceCode":"\t\t\t\tfailed.push((entry, anyhow!(\"Invalid path\")));\n\t\t\t\tcontinue;\n\t\t\t};\n\n\t\t\tlet result: io::Result<()> = if entry.is_dir {\n\t\t\t\tengine::create_dir_all(&dist).await\n\t\t\t} else if let Some(parent) = dist.parent() {\n\t\t\t\tengine::create_dir_all(parent).await.ok();\n\t\t\t\tengine::create_new(&dist).await.map(|_| ())\n\t\t\t} else {\n\t\t\t\tErr(io::Error::other(\"No parent directory\"))\n\t\t\t};\n\n\t\t\tif let Err(e) = result {\n\t\t\t\tfailed.push((entry, e.into()));\n\t\t\t} else if let Ok(f) = engine::file(dist).await {\n\t\t\t\tsucceeded.push(f);\n\t\t\t} else {\n\t\t\t\tfailed.push((entry, anyhow!(\"Failed to retrieve file info\")));\n\t\t\t}\n\t\t}\n\n\t\tif !succeeded.is_empty() {\n\t\t\t// log_if_err!(Pubsub::pub_after_bulk_create(it));  // FIXME\n\t\t\tFilesOp::create(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\n\t\t\t.open","sourceCodeStart":74,"sourceCodeEnd":110,"githubUrl":"https://github.com/sxyazi/yazi/blob/94abcfa92f4ad3f0a1aef6c1ea083cfb8aa6c8c2/yazi-actor/src/mgr/bulk_create.rs#L74-L110","documentation":"After engine::create_dir_all / engine::create_new reports success for an entry, bulk_create stats the new path with engine::file(dist) to build the File handed to FilesOp::create. If that stat fails, the entry is recorded as failed with \"Failed to retrieve file info\" even though the create itself succeeded — the file may well exist on disk.","triggerScenarios":"Create succeeds but the immediately following metadata read fails: eventually-consistent remote/archive backends, the new file being deleted between create and stat by a watcher or concurrent process, or permission loss on the parent directory after creation.","commonSituations":"Bulk creation over network mounts, ssh/smb/archive VFS with metadata lag; large batches while sync clients (Dropbox, rsync jobs) touch the same tree; sandboxed environments restricting stat.","solutions":["Verify on disk first — the file usually exists; refresh the directory listing","Retry the stat once after a short delay (engine::file again) before treating the entry as failed","Pause or exclude sync clients/watchers from the target tree during bulk runs"],"exampleFix":null,"handlingStrategy":"retry","validationCode":null,"typeGuard":null,"tryCatchPattern":"// Treat 'Failed to retrieve file info' as a soft failure: the create likely succeeded.\nif let Ok(_) = result {\n    let f = match engine::file(&dist).await {\n        Ok(f) => f,\n        Err(_) => tokio::time::sleep(std::time::Duration::from_millis(200)).await,\n            engine::file(&dist).await.with_context(|| format!(\"stat after create: {}\", dist))?,\n    };\n    succeeded.push(f);\n}","preventionTips":["Verify on disk before reporting a bulk_create entry as failed","Retry stats once on remote/archive backends","Avoid bulk operations while sync tools modify the same tree"],"tags":["bulk-create","vfs","metadata","race-condition"],"backgroundTag":null,"analyzedSha":"94abcfa92f4ad3f0a1aef6c1ea083cfb8aa6c8c2","analyzedAt":"2026-08-16T09:56:24.836Z","schemaVersion":2},"datasetVersion":"2026-08-16T13:17:31.715Z"}