libnyanpasu/clash-nyanpasu · error

cleanup journal destination has a different payload

Error message

cleanup journal destination has a different payload

What it means

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.

Source

Thrown at backend/tauri/src/service/profile_file.rs:1265

        root: &Path,
        operation_id: &str,
        from: CleanupPhase,
        to: CleanupPhase,
    ) -> anyhow::Result<()> {
        let source = Self::cleanup_path(root, from, operation_id);
        let destination = Self::cleanup_path(root, to, operation_id);
        let source_journal = Self::read_journal(&source, operation_id)?;
        match std::fs::symlink_metadata(&destination) {
            Err(error) if error.kind() == std::io::ErrorKind::NotFound => {
                Self::advance_journal_phase(&source, &destination, &source_journal)
            }
            Ok(metadata) if is_symlink_or_reparse(&metadata) || !metadata.is_file() => bail!(
                "cleanup journal destination is not a regular file: {}",
                destination.display()
            ),
            Ok(_) => {
                if Self::read_journal(&destination, operation_id)? != source_journal {
                    bail!("cleanup journal destination has a different payload");
                }
                Self::remove_private_regular(&source)
            }
            Err(error) => Err(error).context("inspect cleanup journal destination"),
        }
    }

    fn discard_materialization(
        root: &Path,
        operation_id: &str,
        location: JournalLocation,
    ) -> anyhow::Result<()> {
        Self::remove_operation_artifacts(
            root,
            operation_id,
            &Self::journal_path(root, location, operation_id),
        )
    }

View on GitHub (pinned to f7dbce2997)

Solutions

  1. 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.
  2. If you can definitively identify the newer journal, keep it, delete the other, and retry the transition.
  3. Ensure operation ids are unique per cleanup attempt to prevent cross-attempt collisions.
  4. Check storage health if torn journals recur after crashes.

Example fix

// before: ambiguous state, transition always bails
transition_cleanup_journal(root, &id, CleanupPhase::Pending, CleanupPhase::Ready)?;
// after: discard the conflicting cleanup operation
std::fs::remove_file(cleanup_path(root, CleanupPhase::Pending, &id))?;
std::fs::remove_file(cleanup_path(root, CleanupPhase::Ready, &id))?;
start_cleanup(plan)?; // fresh operation_id
Defensive patterns

Strategy: try-catch

Validate before calling

fn cleanup_payloads_agree(root: &Path, id: &str) -> bool {
    match (std::fs::read(cleanup_path(root, CleanupPhase::Pending, id)),
           std::fs::read(cleanup_path(root, CleanupPhase::Ready, id))) {
        (Ok(a), Ok(b)) => a == b,
        _ => true,
    }
}

Try / catch

match transition_cleanup_journal(root, id, from, to) {
    Err(e) if e.to_string().contains("different payload") => {
        // ambiguous destructive cleanup: drop both journals, restart with a new id
    }
    other => other?,
}

Prevention

When it happens

Trigger: 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.

Common situations: 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.

Understand the failure class

Background: "This is a bug, please report it": internal invariant violations, unreachable panics, and SNH errors explained — this error's family across 47 libraries.

Related errors


AI-assisted analysis of libnyanpasu/clash-nyanpasu@f7dbce2997 (2026-09-08). Data as JSON: /api/errors/13d063554fc3b77b. Report an issue: GitHub.