libnyanpasu/clash-nyanpasu · error

journal destination has a different payload

Error message

journal destination has a different payload

What it means

When transition_journal finds the destination phase journal already present as a regular file, it compares the destination journal's payload with the source journal's. If they differ, it bails instead of overwriting, because two journals with the same operation_id but different payloads indicate corrupted or interleaved transaction state. The library intentionally never silently discards either journal.

Source

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

        root: &Path,
        operation_id: &str,
        from: JournalLocation,
        to: JournalLocation,
    ) -> anyhow::Result<()> {
        let source = Self::journal_path(root, from, operation_id);
        let destination = Self::journal_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!(
                "journal destination is not a regular file: {}",
                destination.display()
            ),
            Ok(_) => {
                if Self::read_journal(&destination, operation_id)? != source_journal {
                    bail!("journal destination has a different payload");
                }
                Self::remove_private_regular(&source)
            }
            Err(error) => Err(error).context("inspect journal destination"),
        }
    }

    fn transition_cleanup_journal(
        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 => {

View on GitHub (pinned to f7dbce2997)

Solutions

  1. Treat the operation as unrecoverable: delete all journal files for that operation_id (both phase locations) and re-run the profile operation from scratch.
  2. Compare the two journal files at the printed paths to confirm which attempt is newer, and manually remove the stale one if you must salvage it.
  3. Avoid reusing operation ids across attempts; ensure each materialization generates a fresh id.
  4. If crashes cause this repeatedly, verify disk integrity (fsck/chkdsk) — torn writes suggest storage-level problems.

Example fix

// before: retrying the transition always re-bails
transition_journal(root, &id, from, to)?;
// after: discard the conflicting operation and start over
for loc in [from, to] {
    let _ = std::fs::remove_file(journal_path(root, loc, &id));
}
let prepared = prepare_materialization(...)?; // new operation_id
prepared.commit()?;
Defensive patterns

Strategy: try-catch

Validate before calling

fn journal_payloads_agree(root: &Path, from: JournalLocation, to: JournalLocation, id: &str) -> bool {
    let (a, b) = (journal_path(root, from, id), journal_path(root, to, id));
    match (std::fs::read(a), std::fs::read(b)) {
        (Ok(a), Ok(b)) => a == b,
        _ => true, // missing destination is fine; transition will create it
    }
}

Try / catch

match transition_journal(root, id, from, to) {
    Err(e) if e.to_string().contains("different payload") => {
        // ambiguous transaction: delete all journals for this operation_id and restart
    }
    other => other?,
}

Prevention

When it happens

Trigger: Advancing a journal phase (e.g. staged -> committed for the same operation_id) when the destination already holds a journal written by a different operation/attempt that reused the same operation_id, or a partially-written/damaged journal whose contents no longer match.

Common situations: A crash left both phases populated but the Windows write-through path was interrupted mid-write leaving a torn payload; an operation_id was accidentally regenerated/reused across attempts; a user restored the journal directory from an old backup mixing attempts.

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/62de85644a878233. Report an issue: GitHub.