libnyanpasu/clash-nyanpasu · error
staged symlink hash mismatch
Error message
staged symlink hash mismatch
What it means
The staged symlink-spec file was read, but its target string does not match the expected tagged hash (hash_tagged(b"symlink", target_bytes)). The symlink target changed after staging or the expected hash belongs to a different resource. This integrity check prevents promoting a symlink pointing somewhere other than what was validated.
Source
Thrown at backend/tauri/src/service/profile_file.rs:794
bail!("materialization has multiple staged resources");
}
if let Some(metadata) = file_metadata {
if is_symlink_or_reparse(&metadata) || !metadata.is_file() {
bail!("staged file is not a regular file");
}
let content = std::fs::read(&file_path)?;
if hash_tagged(b"file", &content) != expected_hash {
bail!("staged file hash mismatch");
}
return Ok(Some(StoredResource::File { path: file_path }));
}
if let Some(metadata) = link_metadata {
if is_symlink_or_reparse(&metadata) || !metadata.is_file() {
bail!("staged symlink specification is not a regular file");
}
let target = std::fs::read_to_string(&link_path)?;
if hash_tagged(b"symlink", target.as_bytes()) != expected_hash {
bail!("staged symlink hash mismatch");
}
return Ok(Some(StoredResource::Symlink {
target: ExternalProfilePath::new(target)?,
}));
}
Ok(None)
}
fn capture_backup(root: &Path, operation_id: &str, target: &Path) -> anyhow::Result<()> {
match std::fs::symlink_metadata(target) {
Ok(metadata) if metadata.file_type().is_symlink() => {
let link_target = std::fs::read_link(target)?;
let link_target = link_target
.to_str()
.context("managed symlink target is not valid UTF-8")?;
Self::write_private_file_new(
&Self::backup_link_path(root, operation_id),
link_target.as_bytes(),View on GitHub (pinned to f7dbce2997)
Solutions
- Re-run the materialization so the symlink spec is restaged and the hash recomputed.
- Ensure the expected_hash was computed with hash_tagged(b"symlink", ...) over the same target string that was staged (not the b"file" variant).
- Serialize access to the operation_id — make sure no other task stages/reads the same operation concurrently.
- If a crash left a partial spec file, clear the staging dir for this operation_id before retrying.
Example fix
// before: expected hash computed with wrong domain tag let expected = hash_tagged(b"file", target.as_bytes()); // after: match the staged resource kind let expected = hash_tagged(b"symlink", target.as_bytes());
Defensive patterns
Strategy: retry
Try / catch
match result {
Err(e) if e.to_string().contains("staged symlink hash mismatch") => {
remove_stale_staging(root, op_id)?;
retry_materialization() // restage target string and recompute hash
}
other => other,
} Prevention
- Compute the expected hash with the b"symlink" domain tag, matching the staged resource kind.
- Never reuse operation IDs between file and symlink materializations.
- Avoid concurrent staging/read of the same operation_id.
When it happens
Trigger: std::fs::read_to_string(stage_link_path) succeeded but hash_tagged(b"symlink", target.as_bytes()) != expected_hash — the spec file content changed after staging (concurrent write, crash-partial write), or the caller passed an expected_hash computed for a file resource instead of the symlink resource.
Common situations: Reusing an operation_id with an expected hash from a previous file-based materialization; concurrent modification of the staging directory; a partially flushed write persisted only part of the target string.
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
- staged file hash mismatch
- staged file is not a regular file
- staged symlink specification is not a regular file
- staged resource is missing and target hash does not match
- promoted target hash mismatch
AI-assisted analysis of libnyanpasu/clash-nyanpasu@f7dbce2997 (2026-09-08).
Data as JSON: /api/errors/d60d489323c0de45.
Report an issue: GitHub.