rust-lang/cargo · error
artifact-dir was not locked
Error message
artifact-dir was not locked
What it means
This panic fires in Timings::finished() when cargo tries to write the HTML timing report at the end of a build. The timings output directory lives under the artifact-dir layout (timings_dir() delegates to host.artifact_dir().map(|v| v.timings())), which is only populated when the artifact-dir has been locked during the build. If a logger is present (timings or logging enabled) but the artifact-dir layout is None, the .expect() aborts the process.
Source
Thrown at src/compiler/timings/mod.rs:271
*prev = current;
self.last_cpu_recording = now;
let dur = now.duration_since(self.start).as_secs_f64();
self.cpu_usage.push((dur, 100.0 - pct_idle));
}
/// Call this when all units are finished.
pub fn finished(
&mut self,
build_runner: &BuildRunner<'_, '_>,
error: &Option<anyhow::Error>,
) -> CargoResult<()> {
if let Some(logger) = build_runner.bcx.logger
&& let Some(logs) = logger.get_logs()
{
let timings_path = build_runner
.files()
.timings_dir()
.expect("artifact-dir was not locked");
paths::create_dir_all(&timings_path)?;
let run_id = logger.run_id();
let filename = timings_path.join(format!("cargo-timing-{run_id}.html"));
let mut f = BufWriter::new(paths::create(&filename)?);
let mut ctx = prepare_context(logs.into_iter(), run_id, false)?;
ctx.error = error;
ctx.cpu_usage = &self.cpu_usage;
report::write_html(ctx, &mut f)?;
let unstamped_filename = timings_path.join("cargo-timing.html");
paths::link_or_copy(&filename, &unstamped_filename)?;
let mut shell = self.gctx.shell();
let timing_path = std::env::current_dir().unwrap_or_default().join(&filename);
let link = shell.err_file_hyperlink(&timing_path);
let msg = format!("report saved to {link}{}{link:#}", timing_path.display(),);
shell.status_with_color("Timing", msg, &style::NOTE)?;View on GitHub (pinned to 0e07a15537)
Solutions
- Ensure the build runner calls layout locking (prepare/lock the artifact-dir) before invoking compilation when timings or logging is enabled.
- If using cargo as a library, verify your BuildRunner configuration mirrors what cargo init does for artifact-dir setup.
- Clear the target directory (cargo clean) and rebuild to regenerate fresh layout metadata.
- Update cargo to the latest stable release — if this is an internal regression it will have been fixed.
Example fix
// before
let timings_path = build_runner.files().timings_dir().expect("artifact-dir was not locked");
// after — fall back gracefully instead of panicking
let Some(timings_path) = build_runner.files().timings_dir() else {
tracing::warn!("timings requested but artifact-dir was not locked; skipping report");
return Ok(());
}; Defensive patterns
Strategy: validation
Validate before calling
// Before calling build_runner timings, verify artifact-dir is available
if build_runner.files().timings_dir().is_none() {
eprintln!("warning: timings requested but artifact-dir not locked; skipping");
} else {
timings.finished(build_runner, &error)?;
} Try / catch
// For embedded library users: catch the panic
use std::panic;
let result = panic::catch_unwind(|| {
timings.finished(build_runner, &error)
});
if result.is_err() {
eprintln!("timings report generation panicked; continuing");
} Prevention
- Ensure the build runner establishes artifact-dir layout locking before compilation when timings/logging is enabled.
- Use cargo clean to reset stale layout metadata before builds with --timings.
- Keep cargo updated — internal layout invariants are refined across releases.
When it happens
Trigger: Building with --timings (or [build] timinings = true in config) in a context where the artifact-dir was never locked — e.g., a build runner that was set up without locking the artifact output directory, or a corrupted/interrupted build state where the layout's artifact_dir field is None despite a logger being active.
Common situations: Using cargo as an embedded library with a custom BuildRunner that enables logging but doesn't establish the artifact-dir lock; cargo internals regression after a refactor of layout locking; running --timings against a target directory whose layout metadata is stale or manually deleted.
Related errors
- artifact-dir was not locked during clean
- artifact dep
- already loaded config values
- env var was not array
- was not filled at beginning of the function
AI-assisted analysis of rust-lang/cargo@0e07a15537 (2026-08-06).
Data as JSON: /data/errors/598d092e95589cd5.json.
Report an issue: GitHub.