rust-lang/cargo · error

parent dir for artifacts

Error message

parent dir for artifacts

What it means

When propagating artifact dependency outputs into environment variables (`CARGO_<TYPE>_DIR_<DEP>`), Cargo takes `artifact_path.parent().expect("parent dir for artifacts")`. Artifact output paths come from `build_runner.outputs(...)` and always point at a file inside a directory, so they must have a parent. The panic indicates a malformed output path (empty, or a bare filename with no separator).

Source

Thrown at src/compiler/artifact.rs:60

                .unwrap_or_else(|| OsString::from(format!("placeholder:{name}")));

            let key = format!("CARGO_BIN_EXE_{name}");
            env.insert(key, exe_path);
        }
    }

    for unit_dep in dependencies.iter().filter(|d| d.unit.artifact.is_true()) {
        for artifact_path in build_runner
            .outputs(&unit_dep.unit)?
            .iter()
            .filter_map(|f| (f.flavor == FileFlavor::Normal).then(|| &f.path))
        {
            let artifact_type_upper = unit_artifact_type_name_upper(&unit_dep.unit);
            let dep_name = unit_dep.dep_name.unwrap_or(unit_dep.unit.pkg.name());
            let dep_name_upper = dep_name.to_uppercase().replace("-", "_");

            let var = format!("CARGO_{}_DIR_{}", artifact_type_upper, dep_name_upper);
            let path = artifact_path.parent().expect("parent dir for artifacts");
            env.insert(var, path.to_owned().into());

            let var_file = format!(
                "CARGO_{}_FILE_{}_{}",
                artifact_type_upper,
                dep_name_upper,
                unit_dep.unit.target.name()
            );
            env.insert(var_file, artifact_path.to_owned().into());

            // If the name of the target matches the name of the dependency, we strip the
            // repetition and provide the simpler env-var as well.
            // For backwards-compatibility of inferred names, we compare against the name of the
            // package as well, since that used to be the default for library targets.
            if unit_dep.unit.target.name() == dep_name.as_str() {
                let var = format!("CARGO_{}_FILE_{}", artifact_type_upper, dep_name_upper,);
                env.insert(var, artifact_path.to_owned().into());
            }

View on GitHub (pinned to 0e07a15537)

Solutions

  1. Run `cargo clean` and rebuild — a stale or partially-deleted target dir is the most common cause.
  2. Avoid running `cargo clean` / `rm -rf target` concurrently with a build.
  3. Specify an explicit, non-empty `--target-dir` and `CARGO_TARGET_DIR`.
  4. If using `-Zbindeps`, update to the latest nightly and report the manifest if it reproduces.

Example fix

// before
let path = artifact_path.parent().expect("parent dir for artifacts");
// after
let path = artifact_path.parent().ok_or_else(|| {
    anyhow::anyhow!(
        "artifact output path `{}` has no parent directory",
        artifact_path.display()
    )
})?;
Defensive patterns

Strategy: validation

Validate before calling

// Caller-side: ensure artifact dep outputs resolve to a file path with a parent
fn artifact_has_parent(p: &std::path::Path) -> bool {
    p.parent().map(|d| !d.as_os_str().is_empty()).unwrap_or(false)
}

Prevention

When it happens

Trigger: An artifact dependency whose computed output filename degenerates to a path with no parent component — e.g. an empty `--artifact-dir`/out-dir, or a unit whose `OutputFile::path` was constructed as a bare filename; concurrent `cargo clean` wiping the directory between computation and `.parent()`.

Common situations: Using `-Zbindeps` / artifact dependencies with a custom `--target-dir` or `--artifact-dir` set to an empty/relative string; build scripts that relocate outputs; partial writes during interrupted builds.

Related errors


AI-assisted analysis of rust-lang/cargo@0e07a15537 (2026-08-06). Data as JSON: /data/errors/9269e2ec1b0b6d78.json. Report an issue: GitHub.