{"id":"c17f91a36ebf0c6b","repo":"rust-lang/cargo","slug":"artifact-dir-was-not-locked","errorCode":null,"errorMessage":"artifact-dir was not locked","messagePattern":"artifact-dir was not locked","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src/compiler/build_runner/compilation_files.rs","lineNumber":223,"sourceCode":"        self.metas[unit]\n    }\n\n    /// Gets the short hash based only on the `PackageId`.\n    /// Used for the metadata when `c_extra_filename` returns `None`.\n    fn target_short_hash(&self, unit: &Unit) -> String {\n        let hashable = unit.pkg.package_id().stable_hash(self.ws.root());\n        util::short_hash(&(METADATA_VERSION, hashable))\n    }\n\n    /// Returns the directory where the artifacts for the given unit are\n    /// initially created.\n    pub fn output_dir(&self, unit: &Unit) -> PathBuf {\n        // Docscrape units need to have doc/ set as the out_dir so sources for reverse-dependencies\n        // will be put into doc/ and not into deps/ where the *.examples files are stored.\n        if unit.mode.is_doc() || unit.mode.is_doc_scrape() {\n            self.layout(unit.kind)\n                .artifact_dir()\n                .expect(\"artifact-dir was not locked\")\n                .doc()\n                .to_path_buf()\n        } else if unit.mode.is_doc_test() {\n            panic!(\"doc tests do not have an out dir\");\n        } else if unit.target.is_custom_build() {\n            self.build_script_dir(unit)\n        } else if unit.target.is_example() && !self.ws.gctx().cli_unstable().build_dir_new_layout {\n            self.layout(unit.kind).build_dir().examples().to_path_buf()\n        } else if unit.artifact.is_true() {\n            self.artifact_dir(unit)\n        } else {\n            self.deps_dir(unit).to_path_buf()\n        }\n    }\n\n    /// Additional export directory from `--artifact-dir`.\n    pub fn export_dir(&self) -> Option<PathBuf> {\n        self.export_dir.clone()","sourceCodeStart":205,"sourceCodeEnd":241,"githubUrl":"https://github.com/rust-lang/cargo/blob/0e07a155371a6ce88ae53a2c00df940280c09a67/src/compiler/build_runner/compilation_files.rs#L205-L241","documentation":"`CompilationFiles::output_dir` for doc/doc-scrape units calls `self.layout(unit.kind).artifact_dir().expect(\"artifact-dir was not locked\")`. `artifact_dir()` returns `None` only when no `--artifact-dir` / uplift destination was acquired for that layout. Doc modes that hit this branch are expected to have locked the artifact dir; `None` means the build was configured without one yet still routed a doc unit through the artifact-dir branch — a Cargo-internal inconsistency.","triggerScenarios":"Running `cargo doc` (or doc-scrape for reverse-dependency docs) without an artifact directory set in a code path that assumes one exists; a profile/target combination where `Layout::artifact_dir` was not prepared but `output_dir` still chose the doc branch; misuse of `-Zunstable-options` around `--artifact-dir`.","commonSituations":"Custom profiles or unstable flags that change which layouts get prepared; building docs for a target whose `Layout` was created without locking artifacts; partial target-dir corruption.","solutions":["Run `cargo clean` and retry `cargo doc`.","Drop unstable layout flags (`-Zbuild-dir-new-layout`, `--artifact-dir`) to rule out a layout-routing bug.","If reproducible on stock `cargo doc`, report it upstream with the manifest and target list."],"exampleFix":"// before\nself.layout(unit.kind)\n    .artifact_dir()\n    .expect(\"artifact-dir was not locked\")\n    .doc()\n// after\nlet artifact = self.layout(unit.kind).artifact_dir().ok_or_else(|| {\n    anyhow::anyhow!(\n        \"internal error: artifact dir not locked for doc unit `{}`\",\n        unit.pkg.package_id()\n    )\n})?;\nartifact.doc()","handlingStrategy":"validation","validationCode":"// Confirm the target dir is not being modified concurrently and is writable\nfn target_dir_healthy(p: &std::path::Path) -> bool {\n    p.is_dir() && std::fs::metadata(p).map(|m| m.permissions().readonly() == false).unwrap_or(false)\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Run `cargo clean` before `cargo doc` after switching Cargo versions.","Avoid unstable layout flags unless you need them.","Run a single `cargo doc` per target dir at a time."],"tags":["cargo","layout","artifact-dir","docs","internal-invariant"],"analyzedSha":"0e07a155371a6ce88ae53a2c00df940280c09a67","analyzedAt":"2026-08-06T01:46:58.334Z","schemaVersion":2}