{"record":{"id":"824ba8ea63d57b08","repo":"rust-lang/cargo","slug":"the-manifest-file-needs-to-be-updated-but-lock","errorCode":null,"errorMessage":"the manifest file {} needs to be updated but {locked_flag} was passed to prevent this","messagePattern":"the manifest file (.+?) needs to be updated but (.+?) was passed to prevent this","errorType":"exception","errorClass":"anyhow::Error","httpStatus":null,"severity":"error","filePath":"src/ops/cargo_add/mod.rs","lineNumber":290,"sourceCode":"        }\n        manifest.gc_dep(dep.toml_key());\n    }\n\n    if was_sorted {\n        if let Some(table) = manifest\n            .get_table_mut(&dep_table)\n            .and_then(TomlItem::as_table_like_mut)\n        {\n            table.sort_values();\n        }\n    }\n\n    manifest.ensure_edition();\n\n    if let Some(locked_flag) = options.gctx.locked_flag() {\n        let new_raw_manifest = manifest.to_string();\n        if original_raw_manifest != new_raw_manifest {\n            anyhow::bail!(\n                \"the manifest file {} needs to be updated but {locked_flag} was passed to prevent this\",\n                manifest.path.display()\n            );\n        }\n    }\n\n    if options.dry_run {\n        options.gctx.shell().warn(\"aborting add due to dry run\")?;\n    } else {\n        manifest.write()?;\n    }\n\n    Ok(())\n}\n\n/// Dependency entry operation\n#[derive(Clone, Debug, PartialEq, Eq)]\npub struct DepOp {","sourceCodeStart":272,"sourceCodeEnd":308,"githubUrl":"https://github.com/rust-lang/cargo/blob/98a09e7e7d62850f14e5b6132101fc1edd19a16f/src/ops/cargo_add/mod.rs#L272-L308","documentation":"Thrown by cargo add when the --locked flag is active and the operation would change the Cargo.toml manifest. The --locked flag asserts that no files should be modified beyond what the lockfile expects; cargo add inherently writes to the manifest, creating a conflict.","triggerScenarios":"Running `cargo add <dep> --locked` (or with the CARGO_LOCKED environment variable set) in a context where the dependency addition changes the manifest content.","commonSituations":"CI pipelines that pass --locked to all cargo commands. Scripts that set CARGO_LOCKED globally. Using --locked out of habit without realizing cargo add must write.","solutions":["Remove the --locked flag from the cargo add invocation","Unset the CARGO_LOCKED environment variable: `unset CARGO_LOCKED`","If you need reproducibility, run cargo add without --locked first, commit the manifest change, then use --locked for subsequent build/test commands"],"exampleFix":"# before\ncargo add serde --locked\n# error: the manifest file Cargo.toml needs to be updated\n\n# after — remove --locked for add operations\ncargo add serde","handlingStrategy":"validation","validationCode":"// Detect --locked before running cargo add\nfn should_use_locked(add_command: &str) -> bool {\n    // cargo add inherently modifies the manifest, so --locked is incompatible\n    if add_command.contains(\"--locked\") {\n        eprintln!(\"warning: --locked prevents cargo add from writing; removing it\");\n        return false;\n    }\n    false\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Never pass --locked to cargo add — it must write to the manifest","Unset CARGO_LOCKED before cargo add in CI scripts","Use --locked for build/test/check commands, not for add/update commands"],"tags":["cargo-add","locked","manifest"],"backgroundTag":null,"analyzedSha":"98a09e7e7d62850f14e5b6132101fc1edd19a16f","analyzedAt":"2026-08-11T17:42:36.556Z","contentChangedAt":"2026-08-11T17:42:36.556Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}