rust-lang/cargo · error

the manifest file {} needs to be updated but {locked_flag} w

Error message

the manifest file {} needs to be updated but {locked_flag} was passed to prevent this

What it means

When `--locked` (or the equivalent `locked_flag`) is in effect, cargo-add refuses to modify `Cargo.toml` even though adding the dependency requires writing to it. The function snapshots the raw manifest before processing, applies edits in memory, and if `original_raw_manifest != new_raw_manifest` under a locked flag it bails. This guarantees reproducible, frozen manifests in CI.

Source

Thrown at src/ops/cargo_add/mod.rs:288

        }
        manifest.gc_dep(dep.toml_key());
    }

    if was_sorted {
        if let Some(table) = manifest
            .get_table_mut(&dep_table)
            .and_then(TomlItem::as_table_like_mut)
        {
            table.sort_values();
        }
    }

    manifest.ensure_edition();

    if let Some(locked_flag) = options.gctx.locked_flag() {
        let new_raw_manifest = manifest.to_string();
        if original_raw_manifest != new_raw_manifest {
            anyhow::bail!(
                "the manifest file {} needs to be updated but {locked_flag} was passed to prevent this",
                manifest.path.display()
            );
        }
    }

    if options.dry_run {
        options.gctx.shell().warn("aborting add due to dry run")?;
    } else {
        manifest.write()?;
    }

    Ok(())
}

/// Dependency entry operation
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct DepOp {

View on GitHub (pinned to 0e07a15537)

Solutions

  1. Drop `--locked` from the `cargo add` invocation; adding a dependency is inherently a manifest mutation.
  2. If reproducibility is required, run `cargo add` without `--locked`, commit the new `Cargo.toml` and `Cargo.lock`, and keep `--locked` for subsequent `cargo build`/`cargo generate-lockfile` steps.
  3. Audit `.cargo/config.toml` and your CI matrix for a global `locked = true` or wrapper that injects `--locked`.

Example fix

# before (CI)
cargo add serde --locked

# after
cargo add serde
git commit -am "add serde"
Defensive patterns

Strategy: validation

Validate before calling

// Never pass --locked to an additive operation. Strip it before invoking cargo add.
fn sanitize_add_args(args: &mut Vec<String>) {
    if args.iter().any(|a| a == "add") {
        args.retain(|a| a != "--locked");
    }
}

Prevention

When it happens

Trigger: Running `cargo add <dep> --locked`, or any `cargo add` invocation while `.cargo/config.toml` / environment forces locked mode. Any dependency addition mutates the manifest, so the diff is always non-empty and the bail fires.

Common situations: CI pipelines that pass `--locked` globally to all cargo subcommands, or Dockerfile lines that bake `--locked` into a generic cargo wrapper. The flag is meaningful for `build`/`update` but conflicts with an *additive* manifest operation.

Related errors


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