{"record":{"id":"96fb02306a249e20","repo":"sxyazi/yazi","slug":"failed-to-work-on-task-remote-file-has-chang","errorCode":null,"errorMessage":"Failed to work on: {task:?}: remote file has changed during upload","messagePattern":"Failed to work on: (.+?): remote file has changed during upload","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"yazi-scheduler/src/file/file.rs","lineNumber":450,"sourceCode":"\t\t\tctx!(task, Transaction::tmp(&task.target).await, \"Cannot determine temporary upload path\")?;\n\t\tlet mut rx = ctx!(\n\t\t\ttask,\n\t\t\tengine::copy(cache, &tmp, Attrs {\n\t\t\t\tmode:  Some(cha.mode),\n\t\t\t\tatime: None,\n\t\t\t\tbtime: None,\n\t\t\t\tmtime: None,\n\t\t\t})\n\t\t\t.await\n\t\t)?;\n\n\t\tloop {\n\t\t\tmatch rx.recv().await.unwrap_or(Ok(0)) {\n\t\t\t\tOk(0) => {\n\t\t\t\t\tlet cha =\n\t\t\t\t\t\tctx!(task, Self::cha(&task.target, true, None).await, \"Cannot stat original file\")?;\n\t\t\t\t\tif stamp.sig() != cha.hash_u128_str(&mut [0; 26]) {\n\t\t\t\t\t\tErr(anyhow!(\"Failed to work on: {task:?}: remote file has changed during upload\"))?;\n\t\t\t\t\t}\n\n\t\t\t\t\tctx!(task, engine::rename(&tmp, &task.target).await, \"Cannot persist uploaded file\")?;\n\n\t\t\t\t\tlet cha =\n\t\t\t\t\t\tctx!(task, Self::cha(&task.target, true, None).await, \"Cannot stat uploaded file\")?;\n\t\t\t\t\tctx!(task, Stamp::write(cha, task.target.as_url()).await)?;\n\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\tOk(n) => self.ops.out(task.id, FileOutUploadDo::Adv(n)),\n\t\t\t\tErr(e) => ctx!(task, Err(e))?,\n\t\t\t}\n\t\t}\n\t\tOk(self.ops.out(task.id, FileOutUploadDo::Succ))\n\t}\n\n\tpub(super) async fn cha<U>(url: U, follow: bool, dent: Option<DirEntry>) -> io::Result<Cha>","sourceCodeStart":432,"sourceCodeEnd":468,"githubUrl":"https://github.com/sxyazi/yazi/blob/a541adde4e5b082719a0f21a87eb3eab071ece58/yazi-scheduler/src/file/file.rs#L432-L468","documentation":"During the final phase of an upload, yazi-scheduler re-hashes the original source file and compares its signature hash against the stamp taken before transfer began. If the hashes differ, the source was modified concurrently, so the scheduler aborts the upload (before renaming the temp file into place) to avoid persisting inconsistent or clobbered data.","triggerScenarios":"The file being uploaded is modified (written, appended, truncated) by another process or user while the upload loop is still streaming data; the post-transfer hash `stamp.sig()` then mismatches `cha.hash_u128_str()` of the freshly stat'ed source.","commonSituations":"Editing a file in an editor that writes in-place while it's being uploaded to a remote; log files actively appended to during upload; sync tools or CI scripts touching the same file concurrently.","solutions":["Stop processes writing to the source file, then retry the upload","Upload a stable snapshot: copy the file to a temp location and upload that","Retry the upload — if the file is now quiescent the hash will match","For continuously-written files (logs), use rotation or flush-then-upload sequencing"],"exampleFix":"// before\nstd::fs::copy(\"/var/log/app.log\", \"/tmp/upload-staging\")?; // file keeps growing\n// after\nlet snapshot = std::fs::read(\"/var/log/app.log\")?; // take a point-in-time copy\nstd::fs::write(\"/tmp/upload-staging\", &snapshot)?;","handlingStrategy":"retry","validationCode":"// Compare file size/mtime before and after to detect concurrent modification early\nlet before = std::fs::metadata(path)?;\n// ... upload ...\nlet after = std::fs::metadata(path)?;\nassert_eq!(before.len(), after.len(), \"file modified during upload\");","typeGuard":null,"tryCatchPattern":"match upload_result {\n    Err(e) if e.to_string().contains(\"remote file has changed during upload\") => {\n        backoff_retry(upload, 3);\n    }\n    other => other,\n}","preventionTips":["Quiesce writers (close editors, stop log tailing) before uploading","Upload point-in-time snapshots instead of live files","Use file locking where possible","Keep uploads short to shrink the race window"],"tags":["filesystem","concurrency","upload","hash-mismatch"],"backgroundTag":"file-changed-during-transfer","analyzedSha":"a541adde4e5b082719a0f21a87eb3eab071ece58","analyzedAt":"2026-09-02T18:38:25.566Z","contentChangedAt":"2026-09-02T18:38:25.566Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}