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.
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
- materialization has multiple backups
- staged file is not a regular file
- staged symlink specification is not a regular file
- backup file is not a regular file
- backup symlink specification is not a regular file
AI-assisted analysis of libnyanpasu/clash-nyanpasu@f7dbce2997 (2026-09-08).
Data as JSON: /api/errors/0380be7c4208ad16.
Report an issue: GitHub.
Appendix: 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)