libnyanpasu/clash-nyanpasu · error
materialization has multiple staged resources
Error message
materialization has multiple staged resources
What it means
During an external profile materialization, read_staged_resource expects at most one staged resource (a file blob OR a symlink-spec file) per operation_id under the staging root. It found both the staged file path and the staged symlink-spec path present simultaneously. This means the staging directory is in an inconsistent state, so the code refuses to guess which resource is the real one and aborts.
Source
Thrown at backend/tauri/src/service/profile_file.rs:776
Err(error) => {
return Err(error)
.with_context(|| format!("inspect staged file {}", file_path.display()));
}
};
let link_metadata = match std::fs::symlink_metadata(&link_path) {
Ok(metadata) => Some(metadata),
Err(error) if error.kind() == std::io::ErrorKind::NotFound => None,
Err(error) => {
return Err(error).with_context(|| {
format!(
"inspect staged symlink specification {}",
link_path.display()
)
});
}
};
if file_metadata.is_some() && link_metadata.is_some() {
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");View on GitHub (pinned to f7dbce2997)
Solutions
- Delete the stale staging directory for this operation_id (both staged file and staged link files) and re-run the materialization so only one resource is staged.
- Re-run the materialization with a fresh operation_id so a new, empty staging area is used.
- Check for concurrent processes/tasks using the same operation_id and serialize them.
- If reproducible, inspect stage_resource / cleanup paths in profile_file.rs to confirm the old staged resource is removed before staging a different kind.
Example fix
// before: reusing operation_id with mixed staged leftovers
stage_resource(root, "op-1", &MaterializationResource::File { content });
stage_resource(root, "op-1", &MaterializationResource::Symlink { target }); // leftovers -> two staged resources
// after: clean staging before (re)staging, or use a fresh id
std::fs::remove_dir_all(stage_root.join("op-1")).ok();
stage_resource(root, "op-1", &MaterializationResource::Symlink { target }); Defensive patterns
Strategy: try-catch
Validate before calling
let file_path = stage_file_path(root, op_id);
let link_path = stage_link_path(root, op_id);
if file_path.exists() && link_path.exists() {
// clean stale staging before invoking the operation
std::fs::remove_dir_all(stage_dir(root, op_id))?;
} Try / catch
match result {
Err(e) if e.to_string().contains("multiple staged resources") => {
std::fs::remove_dir_all(stage_dir(root, op_id))?;
retry_with_fresh_operation_id()
}
other => other,
} Prevention
- Use a unique operation_id per materialization attempt (uuid), never reuse across retries with different resource kinds.
- Always wipe the staging directory for an operation_id before staging.
- Serialize materializations that could share an operation_id.
When it happens
Trigger: Both stage_file_path(root, operation_id) and stage_file_path-like stage_link_path(root, operation_id) exist on disk when read_staged_resource is called for the same operation_id — e.g. a previous materialization attempt for the same operation_id staged a file and then re-ran stage_resource with a Symlink resource without cleanup, or leftover staging directories from a crashed run were reused under the same operation_id.
Common situations: A materialization operation crashed partway and was retried with the same operation ID but a different resource kind; manual copying/restoring of the staging directory; concurrent materialization runs sharing one operation_id.
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
- staged file is not a regular file
- staged symlink specification is not a regular file
- materialization has multiple backups
- failed to allocate a unique runtime candidate after 16 attem
- runtime candidate directory is a symlink or reparse point: {
AI-assisted analysis of libnyanpasu/clash-nyanpasu@f7dbce2997 (2026-09-08).
Data as JSON: /api/errors/0380be7c4208ad16.
Report an issue: GitHub.