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

  1. 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.
  2. Re-run the materialization with a fresh operation_id so a new, empty staging area is used.
  3. Check for concurrent processes/tasks using the same operation_id and serialize them.
  4. 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

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


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