{"record":{"id":"13d063554fc3b77b","repo":"libnyanpasu/clash-nyanpasu","slug":"cleanup-journal-destination-has-a-different-payloa","errorCode":null,"errorMessage":"cleanup journal destination has a different payload","messagePattern":"cleanup journal destination has a different payload","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"backend/tauri/src/service/profile_file.rs","lineNumber":1265,"sourceCode":"        root: &Path,\n        operation_id: &str,\n        from: CleanupPhase,\n        to: CleanupPhase,\n    ) -> anyhow::Result<()> {\n        let source = Self::cleanup_path(root, from, operation_id);\n        let destination = Self::cleanup_path(root, to, operation_id);\n        let source_journal = Self::read_journal(&source, operation_id)?;\n        match std::fs::symlink_metadata(&destination) {\n            Err(error) if error.kind() == std::io::ErrorKind::NotFound => {\n                Self::advance_journal_phase(&source, &destination, &source_journal)\n            }\n            Ok(metadata) if is_symlink_or_reparse(&metadata) || !metadata.is_file() => bail!(\n                \"cleanup journal destination is not a regular file: {}\",\n                destination.display()\n            ),\n            Ok(_) => {\n                if Self::read_journal(&destination, operation_id)? != source_journal {\n                    bail!(\"cleanup journal destination has a different payload\");\n                }\n                Self::remove_private_regular(&source)\n            }\n            Err(error) => Err(error).context(\"inspect cleanup journal destination\"),\n        }\n    }\n\n    fn discard_materialization(\n        root: &Path,\n        operation_id: &str,\n        location: JournalLocation,\n    ) -> anyhow::Result<()> {\n        Self::remove_operation_artifacts(\n            root,\n            operation_id,\n            &Self::journal_path(root, location, operation_id),\n        )\n    }","sourceCodeStart":1247,"sourceCodeEnd":1283,"githubUrl":"https://github.com/libnyanpasu/clash-nyanpasu/blob/f7dbce2997c633e484f54788035e770b3ee99773/backend/tauri/src/service/profile_file.rs#L1247-L1283","documentation":"In transition_cleanup_journal, when the destination cleanup-phase journal already exists as a regular file, its payload must equal the source journal's payload. A mismatch means two journals under the same operation_id disagree, so the library bails instead of guessing which cleanup attempt is authoritative — deleting profile files is destructive, so ambiguity is fatal.","triggerScenarios":"Advancing the cleanup journal Pending -> Ready when the Ready slot already holds a journal from a different attempt (reused operation_id), or the journal file was corrupted/torn by a crash or storage fault so its payload no longer matches the Pending copy.","commonSituations":"Crash during the Windows write-then-delete phase advance leaving a partially written Ready journal; a backup restore that mixed cleanup attempts; manual copying of journal files between operations.","solutions":["Delete both cleanup journal files for that operation_id and re-run the cleanup operation from scratch — do not guess which payload is correct since cleanup deletes files.","If you can definitively identify the newer journal, keep it, delete the other, and retry the transition.","Ensure operation ids are unique per cleanup attempt to prevent cross-attempt collisions.","Check storage health if torn journals recur after crashes."],"exampleFix":"// before: ambiguous state, transition always bails\ntransition_cleanup_journal(root, &id, CleanupPhase::Pending, CleanupPhase::Ready)?;\n// after: discard the conflicting cleanup operation\nstd::fs::remove_file(cleanup_path(root, CleanupPhase::Pending, &id))?;\nstd::fs::remove_file(cleanup_path(root, CleanupPhase::Ready, &id))?;\nstart_cleanup(plan)?; // fresh operation_id","handlingStrategy":"try-catch","validationCode":"fn cleanup_payloads_agree(root: &Path, id: &str) -> bool {\n    match (std::fs::read(cleanup_path(root, CleanupPhase::Pending, id)),\n           std::fs::read(cleanup_path(root, CleanupPhase::Ready, id))) {\n        (Ok(a), Ok(b)) => a == b,\n        _ => true,\n    }\n}","typeGuard":null,"tryCatchPattern":"match transition_cleanup_journal(root, id, from, to) {\n    Err(e) if e.to_string().contains(\"different payload\") => {\n        // ambiguous destructive cleanup: drop both journals, restart with a new id\n    }\n    other => other?,\n}","preventionTips":["Never reuse an operation_id across cleanup attempts","Restart cleanup from scratch on any payload-mismatch error — deletion is destructive","Check storage health after crashes that precede this error","Do not hand-copy journals between operations"],"tags":["filesystem","crash-recovery","cleanup","data-integrity"],"backgroundTag":"internal-invariant-violation","analyzedSha":"f7dbce2997c633e484f54788035e770b3ee99773","analyzedAt":"2026-09-08T01:24:59.197Z","contentChangedAt":"2026-09-08T01:24:59.197Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}