rust-lang/cargo · error
artifact-dir was not locked
Error message
artifact-dir was not locked
What it means
In the rustdoc fingerprint path, when a fingerprint mismatch is detected Cargo clears the doc directory via `layout(kind).artifact_dir().expect("artifact-dir was not locked")` — the same invariant as in `CompilationFiles::output_dir`. The doc layout's artifact dir must have been acquired; `None` means a doc fingerprint refresh is running against a layout that was never locked, an internal inconsistency.
Source
Thrown at src/compiler/fingerprint/rustdoc.rs:246
on_disk_fingerprint.rustc_vv,
new_fingerprint.rustc_vv
);
}
}
Err(e) => {
tracing::debug!("could not deserialize {:?}: {}", fingerprint_path, e);
}
};
// Fingerprint does not match, delete the doc directories and write a new fingerprint.
tracing::debug!(
"fingerprint {:?} mismatch, clearing doc directories",
fingerprint_path
);
let doc_dir = build_runner
.files()
.layout(kind)
.artifact_dir()
.expect("artifact-dir was not locked")
.doc();
if doc_dir.exists() {
clean_doc(doc_dir)?;
}
write_fingerprint()?;
Ok(())
}
/// Loads an on-disk fingerprint JSON file.
fn load_on_disk(path: &Path) -> Option<RustdocFingerprintJson> {
let on_disk = match paths::read(path) {
Ok(data) => data,
Err(e) => {
tracing::debug!("failed to read rustdoc fingerprint at {path:?}: {e}");
return None;
}View on GitHub (pinned to 0e07a15537)
Solutions
- `cargo clean --doc` (or full `cargo clean`) to remove the stale rustdoc fingerprint and let it rebuild.
- Run a single `cargo doc` at a time per target dir.
- Drop unstable doc/layout flags and retry.
Example fix
// before
let doc_dir = build_runner
.files()
.layout(kind)
.artifact_dir()
.expect("artifact-dir was not locked")
.doc();
// after
let doc_dir = build_runner
.files()
.layout(kind)
.artifact_dir()
.ok_or_else(|| anyhow::anyhow!("rustdoc fingerprint refresh: artifact dir for kind `{:?}` was not locked", kind))?
.doc(); Defensive patterns
Strategy: validation
Validate before calling
// Confirm the rustdoc fingerprint dir is intact before `cargo doc`
fn doc_fingerprint_intact(target: &std::path::Path) -> bool {
target.join(".rustdoc_fingerprint.json").exists() || true // absence just triggers a rebuild
} Prevention
- Run `cargo clean --doc` after switching rustdoc versions.
- Run a single `cargo doc` per target dir at a time.
- Drop unstable doc/layout flags if you see this recurrently.
When it happens
Trigger: Running `cargo doc` and hitting a rustdoc fingerprint mismatch (e.g. after a Cargo/rustdoc version change) on a code path where the artifact dir was not prepared; concurrent `cargo clean` removing the layout's lock files; a profile/flag combination that skips artifact-dir preparation but still runs the rustdoc fingerprint check.
Common situations: Switching rustdoc versions across `cargo doc` runs without `cargo clean`; multiple `cargo doc` invocations on the same target dir; unstable doc flags altering layout preparation.
Related errors
- artifact-dir was not locked
- output must exist after running
- failed to find rmeta
- cannot open specified crate's documentation: no documentatio
- required(true)
AI-assisted analysis of rust-lang/cargo@0e07a15537 (2026-08-06).
Data as JSON: /data/errors/e1436b4fb2922297.json.
Report an issue: GitHub.