libnyanpasu/clash-nyanpasu · error
staged resource is missing and target hash does not match
Error message
staged resource is missing and target hash does not match
What it means
promote_resource could not read the staged resource for the operation, and the target file at its final location does not hash to the expected value. Together this means neither the staging area nor the target holds the verified content, so the transaction cannot be considered complete and it fails instead of silently promoting unverified data.
Source
Thrown at backend/tauri/src/service/profile_file.rs:910
Err(error) => return Err(error).context("inspect ready symlink"),
}
Ok(ready)
}
fn promote_resource(
&self,
root: &Path,
operation_id: &str,
target: &Path,
expected_hash: &str,
) -> anyhow::Result<()> {
self.ensure_managed_parent(target)?;
Self::ensure_replaceable_target(target)?;
let Some(resource) = Self::read_staged_resource(root, operation_id, expected_hash)? else {
if Self::path_hash(target)? == expected_hash {
return Ok(());
}
bail!("staged resource is missing and target hash does not match");
};
// Static symlink/reparse validation is mandatory. A same-user parent
// swap after this recheck is outside this desktop app's local trust
// boundary; descriptor-based confinement is intentionally not added.
match resource {
StoredResource::File { path } => {
self.ensure_managed_parent(target)?;
Self::ensure_replaceable_target(target)?;
replace_atomic(&path, target).with_context(|| {
format!(
"promote staged file {} -> {}",
path.display(),
target.display()
)
})?;
}
StoredResource::Symlink {View on GitHub (pinned to f7dbce2997)
Solutions
- Re-download/re-materialize the profile resource: create a new operation via prepare_materialization so the staged file is recreated, then promote.
- Restore the staged resource file for this operation_id (correct hash) and rerun promote.
- If the target is actually correct, recompute its hash and confirm expected_hash in the journal matches; a stale journal hash is the real bug.
- Run compensate to roll the operation back cleanly before retrying.
Example fix
// before // staged file deleted by cleanup, target no longer matches journal hash // after let op_id = client.prepare_materialization(&managed_path, resource).await?; client.promote(root, &op_id).await?;
Defensive patterns
Strategy: retry
Validate before calling
// caller-side sanity check before promote
let staged_exists = staged_resource_path(root, op_id).exists();
let target_hash = hash_file(&target_path)?;
if !staged_exists && target_hash != expected_hash {
// re-materialize instead of promoting
let new_id = client.prepare_materialization(&managed_path, resource).await?;
} Type guard
fn staged_resource_available(root: &Path, op_id: &str, expected: &str) -> bool {
read_staged_resource_hash(root, op_id).map(|h| h == expected).unwrap_or(false)
} Try / catch
match client.promote(root, op_id).await {
Err(e) if e.to_string().contains("staged resource is missing") => {
let fresh = client.prepare_materialization(&managed_path, resource).await?;
client.promote(root, &fresh).await
}
r => r,
} Prevention
- Promote promptly after prepare; don't leave operations staged across cleanup windows.
- Exclude staging dirs from disk cleaners and tmp reapers.
- Verify profile files aren't edited concurrently by editors or sync clients.
- Reconcile journals at startup to detect lost staged resources early.
When it happens
Trigger: promote() called when the staged resource file is missing (deleted, never written, or lost across journal locations) AND the target's content hash differs from expected_hash — e.g. an interrupted prepare_materialization plus a partially modified target.
Common situations: Disk cleanup removed staging files between runs; a crash occurred after journal creation but before staging completed; the target was edited or corrupted by another process; migrating staging dirs between machines.
Understand the failure class
Background: Checksum mismatch errors: "checksum verification failed", "digest mismatch", "expected vs actual checksum" — what they mean and how to fix them — this error's family across 41 libraries.
Related errors
- promoted target hash mismatch
- materialization journal operation id mismatch
- staged file hash mismatch
- staged symlink hash mismatch
- failed to allocate a unique runtime candidate after 16 attem
AI-assisted analysis of libnyanpasu/clash-nyanpasu@f7dbce2997 (2026-09-08).
Data as JSON: /api/errors/551849ff1a4a0973.
Report an issue: GitHub.