rust-lang/cargo · error · AlreadyPrintedError
cannot clean `{}`: {err}
Error message
cannot clean `{}`: {err} What it means
When `--target-dir` is passed explicitly, `cargo clean` validates that the directory is genuinely a cargo target dir by checking its `CACHEDIR.TAG` file. If `validate_target_dir_tag` returns an error (missing file, invalid signature, symlinked tag), cleaning is aborted with the failure reason and the standard "cleaning has been aborted to prevent accidental deletion" note. This prevents `cargo clean --target-dir <random-dir>` from nuking unrelated directories.
Source
Thrown at src/ops/cargo_clean.rs:87
return Err(crate::AlreadyPrintedError::new(anyhow::anyhow!("")).into());
}
}
// do some validation on target_dir if it was specified via --target-dir
if opts.explicit_target_dir_arg {
let target_dir_path = target_dir.as_path_unlocked();
// perform validation on target_dir only if it exists and check if the target directory has a valid CACHEDIR.TAG
if target_dir_path.exists()
&& let Err(err) = validate_target_dir_tag(target_dir_path)
{
// if target_dir was passed explicitly via --target-dir, then hard error if validation fails
let title = format!("cannot clean `{}`: {err}", target_dir_path.display());
let report = [Level::ERROR
.primary_title(title)
.element(Level::NOTE.message(CLEAN_ABORT_NOTE))];
gctx.shell().print_report(&report, false)?;
return Err(crate::AlreadyPrintedError::new(anyhow::anyhow!("")).into());
}
}
if opts.doc {
if !opts.spec.is_empty() {
// FIXME: https://github.com/rust-lang/cargo/issues/8790
// This should support the ability to clean specific packages
// within the doc directory. It's a little tricky since it
// needs to find all documentable targets, but also consider
// the fact that target names might overlap with dependency
// names and such.
bail!("--doc cannot be used with -p");
}
// If the doc option is set, we just want to delete the doc directory.
target_dir = target_dir.join("doc");
clean_ctx.remove_paths(&[target_dir.into_path_unlocked()])?;
} else {
let profiles = Profiles::new(&ws, opts.requested_profile)?;View on GitHub (pinned to 0e07a15537)
Solutions
- Confirm the directory is really a cargo target dir (it should contain `CACHEDIR.TAG` with the canonical signature).
- Run `cargo clean` *without* `--target-dir` to clean the default target dir, or rebuild in the explicit dir first so the tag is regenerated.
- If the directory is stale, delete it manually (`rm -rf <dir>`) outside of cargo.
Example fix
# before cargo clean --target-dir ./out # ./out has no CACHEDIR.TAG # after (clean the real target dir) cargo clean
Defensive patterns
Strategy: validation
Validate before calling
// When using --target-dir, ensure it carries a valid CACHEDIR.TAG before cleaning.
use std::path::Path;
const SIG: &[u8] = b"Signature: 8a477f597d28d172789f06886806bc55";
fn is_cargo_target_dir(path: &Path) -> bool {
let tag = path.join("CACHEDIR.TAG");
!tag.is_symlink() && tag.is_file() && std::fs::read(&tag).map(|b| b.starts_with(SIG)).unwrap_or(false)
}
// if !is_cargo_target_dir(&dir) { return Err("not a cargo target dir".into()); } Prevention
- Only pass `--target-dir` to directories cargo itself created.
- Prefer the default target dir unless you have a strong reason to relocate.
- Delete stale non-cargo directories manually rather than via `cargo clean`.
When it happens
Trigger: `cargo clean --target-dir <path>` where `<path>` lacks a valid `CACHEDIR.TAG`, e.g. an arbitrary user directory, an empty dir, or one whose tag file has the wrong signature.
Common situations: Pointing `--target-dir` at a project's `dist/` or `out/` folder, a typo in the path, or a directory that was created by a non-cargo tool.
Related errors
- cannot clean `{}`: not a directory
- crate name is empty
- dependency name is required
- failed to open `{}`: {}
- package ID specification `{}` did not match any packages{}
AI-assisted analysis of rust-lang/cargo@0e07a15537 (2026-08-06).
Data as JSON: /data/errors/4b1747e7242af223.json.
Report an issue: GitHub.