libnyanpasu/clash-nyanpasu · critical

promoted target hash mismatch

Error message

promoted target hash mismatch

What it means

promote_resource verifies the final target after replacement by hashing it; the hash differs from expected_hash. This is the last-line integrity check ensuring the promoted file content is exactly what was staged and journaled, so a mismatch aborts the operation as failed rather than reporting success with corrupted data.

Source

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

                })?;
            }
            StoredResource::Symlink {
                target: link_target,
            } => {
                let ready = Self::create_ready_link(root, operation_id, &link_target)?;
                self.ensure_managed_parent(target)?;
                Self::ensure_replaceable_target(target)?;
                replace_atomic(&ready, target).with_context(|| {
                    format!(
                        "promote staged symlink {} -> {}",
                        ready.display(),
                        target.display()
                    )
                })?;
            }
        }
        if Self::path_hash(target)? != expected_hash {
            bail!("promoted target hash mismatch");
        }
        Ok(())
    }

    fn backup_hash(root: &Path, operation_id: &str) -> anyhow::Result<String> {
        match Self::read_backup_resource(root, operation_id)? {
            Some(StoredResource::File { path }) => {
                let content = std::fs::read(&path)
                    .with_context(|| format!("read backup file {}", path.display()))?;
                Ok(hash_tagged(b"file", &content))
            }
            Some(StoredResource::Symlink { target }) => {
                Ok(hash_tagged(b"symlink", target.as_str().as_bytes()))
            }
            None => Ok(ABSENT_HASH.to_owned()),
        }
    }

View on GitHub (pinned to f7dbce2997)

Solutions

  1. Rerun the whole materialization with a fresh operation id so a clean staged copy replaces the corrupted target.
  2. Restore the target from the operation's backup (read_backup_resource / backup restore path) and re-attempt promote.
  3. Investigate what concurrently modified the target (sync tools, editors, antivirus) and exclude the profile directory.
  4. Verify disk health if corruption repeats across operations.

Example fix

// before
// target modified by another process during promote -> hash mismatch
// after
// close/sync tools writing to profiles dir, then:
client.compensate(root, operation_id).await?;
let new_id = client.prepare_materialization(&managed_path, resource).await?;
client.promote(root, &new_id).await?;
Defensive patterns

Strategy: try-catch

Validate before calling

let hash = hash_file(&target_path)?;
if hash != expected_hash {
    // target already diverged; restore from backup or re-materialize before promote
    restore_from_backup(root, op_id, &target_path)?;
}

Type guard

fn target_matches_expected(target: &Path, expected: &str) -> bool {
    hash_file(target).map(|h| h == expected).unwrap_or(false)
}

Try / catch

match client.promote(root, op_id).await {
    Err(e) if e.to_string().contains("hash mismatch") => {
        // rollback to backup, then retry with a fresh operation
        client.compensate(root, op_id).await?;
        let fresh = client.prepare_materialization(&managed_path, resource).await?;
        client.promote(root, &fresh).await
    }
    r => r,
}

Prevention

When it happens

Trigger: promote() completed its copy/rename steps but the resulting target hashes differently — e.g. concurrent writes to the target, a copy that read a source mutated mid-flight, filesystem corruption, or the staged resource itself was tampered with after its hash check.

Common situations: Another process (editor, sync client) wrote the target during promotion; staged source was modified between prepare and promote; disk/filesystem errors silently corrupting content; target on a network mount with unreliable semantics.

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


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