rust-lang/cargo · error

files in the working directory contain changes that were…

Error message

{} files in the working directory contain changes that were not yet committed into git:

{}

to proceed despite this and include the uncommitted changes, pass the `--allow-dirty` flag

What it means

Thrown during `cargo package` or `cargo publish` when the working directory of a git repository contains source files with uncommitted modifications. Cargo refuses to package dirty trees to ensure reproducible published artifacts. The `--allow-dirty` flag overrides this guard.

Solutions

  1. Commit or stash the uncommitted changes, then re-run `cargo package`.
  2. Pass `--allow-dirty` to include uncommitted changes: `cargo package --allow-dirty`.
  3. Add generated or irrelevant files to `.gitignore` so they are not tracked.

Example fix

# Option 1: commit first
git add -A && git commit -m "prep for publish"

# Option 2: allow dirty
cargo package --allow-dirty
Defensive patterns

Strategy: validation

Validate before calling

// Pre-check git status for dirty files before packaging
fn check_git_clean(repo_root: &Path) -> Result<(), String> {
    let output = std::process::Command::new("git")
        .args(["status", "--porcelain"])
        .current_dir(repo_root)
        .output().map_err(|e| e.to_string())?;
    if !output.stdout.is_empty() {
        return Err(format!("uncommitted changes:\n{}", String::from_utf8_lossy(&output.stdout)));
    }
    Ok(())
}

Prevention

When it happens

Trigger: Running `cargo package` (without `--allow-dirty`) when `git status` shows modified, staged-but-uncommitted, or untracked source files within the package. The check uses `gix` status to enumerate dirty files and compares them against the source file set.

Common situations: Forgetting to `git commit` before publishing; having generated files (e.g. from a code generator) that are tracked but locally modified; working on changes and wanting to test packaging mid-development.

Related errors


AI-assisted analysis of rust-lang/cargo@eb98b54bc9 (2026-08-11). Data as JSON: /api/errors/85f7c9fdb7f3d099. Report an issue: GitHub.

Appendix: source

Thrown at src/ops/cargo_package/vcs.rs:264

        .chain(dirty_files_outside_pkg_root(ws, pkg, repo, src_files)?.iter())
        .map(|path| {
            pathdiff::diff_paths(path, cwd)
                .as_ref()
                .unwrap_or(path)
                .display()
                .to_string()
        })
        .collect();
    let dirty = !dirty_src_files.is_empty();
    if !dirty || opts.allow_dirty {
        let maybe_head_id = repo.head()?.try_peel_to_id()?;
        Ok(maybe_head_id.map(|id| GitVcsInfo {
            sha1: id.to_string(),
            dirty,
        }))
    } else {
        dirty_src_files.sort_unstable();
        anyhow::bail!(
            "{} files in the working directory contain changes that were \
             not yet committed into git:\n\n{}\n\n\
             to proceed despite this and include the uncommitted changes, pass the `--allow-dirty` flag",
            dirty_src_files.len(),
            dirty_src_files.join("\n")
        )
    }
}

/// Helper to collect dirty statuses for a single repo.
/// `relative_package_root` is `Some` if the root is a sub-directory of the workdir.
/// Writes dirty files outside `relative_package_root` into `dirty_files_outside_package_root`,
/// and all *everything else* into `dirty_files`.
#[must_use]
fn collect_statuses(
    repo: &gix::Repository,
    workdir: &Path,
    relative_package_root: Option<&Path>,

View on GitHub (pinned to eb98b54bc9)