{"id":"9269e2ec1b0b6d78","repo":"rust-lang/cargo","slug":"parent-dir-for-artifacts","errorCode":null,"errorMessage":"parent dir for artifacts","messagePattern":"parent dir for artifacts","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src/compiler/artifact.rs","lineNumber":60,"sourceCode":"                .unwrap_or_else(|| OsString::from(format!(\"placeholder:{name}\")));\n\n            let key = format!(\"CARGO_BIN_EXE_{name}\");\n            env.insert(key, exe_path);\n        }\n    }\n\n    for unit_dep in dependencies.iter().filter(|d| d.unit.artifact.is_true()) {\n        for artifact_path in build_runner\n            .outputs(&unit_dep.unit)?\n            .iter()\n            .filter_map(|f| (f.flavor == FileFlavor::Normal).then(|| &f.path))\n        {\n            let artifact_type_upper = unit_artifact_type_name_upper(&unit_dep.unit);\n            let dep_name = unit_dep.dep_name.unwrap_or(unit_dep.unit.pkg.name());\n            let dep_name_upper = dep_name.to_uppercase().replace(\"-\", \"_\");\n\n            let var = format!(\"CARGO_{}_DIR_{}\", artifact_type_upper, dep_name_upper);\n            let path = artifact_path.parent().expect(\"parent dir for artifacts\");\n            env.insert(var, path.to_owned().into());\n\n            let var_file = format!(\n                \"CARGO_{}_FILE_{}_{}\",\n                artifact_type_upper,\n                dep_name_upper,\n                unit_dep.unit.target.name()\n            );\n            env.insert(var_file, artifact_path.to_owned().into());\n\n            // If the name of the target matches the name of the dependency, we strip the\n            // repetition and provide the simpler env-var as well.\n            // For backwards-compatibility of inferred names, we compare against the name of the\n            // package as well, since that used to be the default for library targets.\n            if unit_dep.unit.target.name() == dep_name.as_str() {\n                let var = format!(\"CARGO_{}_FILE_{}\", artifact_type_upper, dep_name_upper,);\n                env.insert(var, artifact_path.to_owned().into());\n            }","sourceCodeStart":42,"sourceCodeEnd":78,"githubUrl":"https://github.com/rust-lang/cargo/blob/0e07a155371a6ce88ae53a2c00df940280c09a67/src/compiler/artifact.rs#L42-L78","documentation":"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).","triggerScenarios":"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()`.","commonSituations":"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.","solutions":["Run `cargo clean` and rebuild — a stale or partially-deleted target dir is the most common cause.","Avoid running `cargo clean` / `rm -rf target` concurrently with a build.","Specify an explicit, non-empty `--target-dir` and `CARGO_TARGET_DIR`.","If using `-Zbindeps`, update to the latest nightly and report the manifest if it reproduces."],"exampleFix":"// before\nlet path = artifact_path.parent().expect(\"parent dir for artifacts\");\n// after\nlet path = artifact_path.parent().ok_or_else(|| {\n    anyhow::anyhow!(\n        \"artifact output path `{}` has no parent directory\",\n        artifact_path.display()\n    )\n})?;","handlingStrategy":"validation","validationCode":"// Caller-side: ensure artifact dep outputs resolve to a file path with a parent\nfn artifact_has_parent(p: &std::path::Path) -> bool {\n    p.parent().map(|d| !d.as_os_str().is_empty()).unwrap_or(false)\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Don't run `cargo clean` / `rm -rf target` concurrently with a build.","Set a concrete non-empty `--target-dir` / `CARGO_TARGET_DIR`.","Use a stable Cargo when relying on `-Zbindeps`."],"tags":["cargo","artifact-dependencies","bindeps","path-handling","internal-invariant"],"analyzedSha":"0e07a155371a6ce88ae53a2c00df940280c09a67","analyzedAt":"2026-08-06T01:46:58.334Z","schemaVersion":2}