libnyanpasu/clash-nyanpasu · error
cleanup journals have conflicting payloads
Error message
cleanup journals have conflicting payloads
What it means
When locate_cleanup finds journals in both the Pending and Ready phase slots for the same operation_id, it requires their payloads to be identical (a crash between the Windows write-through and source deletion can legitimately leave both). If the two journals disagree, the library bails rather than choosing a phase, because advancing cleanup with the wrong journal could delete the wrong profile files.
Source
Thrown at backend/tauri/src/service/profile_file.rs:1360
Err(error) => return Err(error).context("inspect pending cleanup journal"),
};
let ready = match std::fs::symlink_metadata(&ready_path) {
Ok(metadata) if !is_symlink_or_reparse(&metadata) && metadata.is_file() => {
Some(Self::read_journal(&ready_path, operation_id)?)
}
Ok(_) => bail!("ready cleanup journal is not a regular file"),
Err(error) if error.kind() == std::io::ErrorKind::NotFound => None,
Err(error) => return Err(error).context("inspect ready cleanup journal"),
};
match (pending, ready) {
(None, None) => Ok(None),
(Some(journal), None) => Ok(Some((CleanupPhase::Pending, journal))),
(None, Some(journal)) => Ok(Some((CleanupPhase::Ready, journal))),
(Some(pending), Some(ready)) if pending == ready => {
Self::remove_private_regular(&pending_path)?;
Ok(Some((CleanupPhase::Ready, ready)))
}
(Some(_), Some(_)) => bail!("cleanup journals have conflicting payloads"),
}
}
fn has_materialization_journal(root: &Path, operation_id: &str) -> bool {
JournalLocation::ALL.iter().any(|location| {
std::fs::symlink_metadata(Self::journal_path(root, *location, operation_id)).is_ok()
})
}
fn has_cleanup_journal(root: &Path, operation_id: &str) -> bool {
[CleanupPhase::Pending, CleanupPhase::Ready]
.iter()
.any(|phase| {
std::fs::symlink_metadata(Self::cleanup_path(root, *phase, operation_id)).is_ok()
})
}
fn remove_cleanup_tombstone(root: &Path, operation_id: &str) -> anyhow::Result<()> {View on GitHub (pinned to f7dbce2997)
Solutions
- Discard the whole cleanup operation: remove both Pending and Ready journals for that operation_id and restart the cleanup with a new operation id.
- Only if you can prove which payload is current (timestamps, transaction log), keep the matching pair by deleting the stale one and retry.
- Never reuse operation ids across cleanup attempts.
- Investigate disk health / crash frequency if divergent journals appear regularly.
Example fix
// before: recovery cannot disambiguate let state = locate_cleanup(root, &id)?; // after: abandon the ambiguous cleanup entirely std::fs::remove_file(cleanup_path(root, CleanupPhase::Pending, &id))?; std::fs::remove_file(cleanup_path(root, CleanupPhase::Ready, &id))?; start_cleanup(new_plan)?; // fresh operation_id
Defensive patterns
Strategy: try-catch
Validate before calling
fn cleanup_pair_agrees(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 locate_cleanup(root, id) {
Err(e) if e.to_string().contains("conflicting payloads") => {
// ambiguous cleanup: delete both journals and start a new cleanup attempt
}
other => other,
} Prevention
- Use a unique operation_id per cleanup attempt
- Never restore only one phase journal from a backup
- Treat payload conflicts as corruption and abandon the operation
- Monitor for crashes/storage faults that precede divergent journals
When it happens
Trigger: Recovery after a crash where both cleanup phases exist but were written by different attempts sharing an operation_id, or one journal was corrupted/torn so its payload no longer matches its sibling; mixing journals restored from backups of different runs.
Common situations: Storage faults or forced power-off mid transition producing divergent copies; an operation_id reused across cleanup attempts; manual copying of a single phase journal during debugging, leaving a stale sibling behind.
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
- cleanup journal destination has a different payload
- journal destination has a different payload
- cleanup journal destination is not a regular file: {}
- journal destination is not a regular file: {}
- pending cleanup journal is not a regular file
AI-assisted analysis of libnyanpasu/clash-nyanpasu@f7dbce2997 (2026-09-08).
Data as JSON: /api/errors/b1c55ff4268100a5.
Report an issue: GitHub.