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

  1. Confirm the directory is really a cargo target dir (it should contain `CACHEDIR.TAG` with the canonical signature).
  2. Run `cargo clean` *without* `--target-dir` to clean the default target dir, or rebuild in the explicit dir first so the tag is regenerated.
  3. 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

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


AI-assisted analysis of rust-lang/cargo@0e07a15537 (2026-08-06). Data as JSON: /data/errors/4b1747e7242af223.json. Report an issue: GitHub.