{"id":"2129f037e62f0f96","repo":"rust-lang/cargo","slug":"you-can-t-generate-a-lockfile-for-an-empty-workspa","errorCode":null,"errorMessage":"you can't generate a lockfile for an empty workspace.","messagePattern":"you can't generate a lockfile for an empty workspace\\.","errorType":"validation","errorClass":"anyhow::Error","httpStatus":null,"severity":"error","filePath":"src/ops/cargo_update.rs","lineNumber":66,"sourceCode":"        &CliFeatures::new_all(true),\n        HasDevUnits::Yes,\n        previous_resolve,\n        None,\n        &[],\n        true,\n    )?;\n    ops::write_pkg_lockfile(ws, &mut resolve)?;\n    print_lockfile_changes(ws, previous_resolve, &resolve, &mut registry)?;\n    Ok(())\n}\n\npub fn update_lockfile(ws: &Workspace<'_>, opts: &UpdateOptions<'_>) -> CargoResult<()> {\n    if opts.recursive && opts.precise.is_some() {\n        anyhow::bail!(\"cannot specify both recursive and precise simultaneously\")\n    }\n\n    if ws.members().count() == 0 {\n        anyhow::bail!(\"you can't generate a lockfile for an empty workspace.\")\n    }\n\n    // Updates often require a lot of modifications to the registry, so ensure\n    // that we're synchronized against other Cargos.\n    let _lock = ws\n        .gctx()\n        .acquire_package_cache_lock(CacheLockMode::DownloadExclusive)?;\n\n    let previous_resolve = match ops::load_pkg_lockfile(ws)? {\n        Some(resolve) => resolve,\n        None => {\n            match opts.precise {\n                None => return generate_lockfile(ws),\n\n                // Precise option specified, so calculate a previous_resolve required\n                // by precise package update later.\n                Some(_) => {\n                    let mut registry = ws.package_registry()?;","sourceCodeStart":48,"sourceCodeEnd":84,"githubUrl":"https://github.com/rust-lang/cargo/blob/0e07a155371a6ce88ae53a2c00df940280c09a67/src/ops/cargo_update.rs#L48-L84","documentation":"update_lockfile requires at least one workspace member to resolve dependencies for. If ws.members().count() == 0 (a virtual manifest with no members, or all members excluded) it bails at cargo_update.rs:66 — there is nothing to put in a lockfile.","triggerScenarios":"Running `cargo update` in a virtual workspace whose `members = []` is empty or whose globs/excludes resolve to zero crates.","commonSituations":"Brand-new workspace before any member crate exists; over-aggressive `exclude` patterns removing all members; `default-members` set but `members` empty.","solutions":["Add at least one member crate to the workspace (create a crate and list it under [workspace] members).","Fix member/exclude globs so at least one real package resolves.","Run `cargo update` from inside an actual package directory instead of the virtual root."],"exampleFix":"# before\n[workspace]\nmembers = []\n\n$ cargo update\nerror: you can't generate a lockfile for an empty workspace.\n\n# after\n[workspace]\nmembers = [\"crates/*\"]\n# and ensure crates/my-crate/Cargo.toml exists with [package]","handlingStrategy":"validation","validationCode":"# Require at least one workspace member before updating:\ncount=$(cargo metadata --no-deps --format-version 1 2>/dev/null \\\n  | jq '.packages|length')\nif [ \"${count:-0}\" -eq 0 ]; then\n  echo \"empty workspace; add a member crate\" >&2; exit 1\nfi\ncargo update","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Ensure [workspace] members globs resolve to at least one package.","Run `cargo update` from inside a real package if the root is virtual.","Double-check `exclude` patterns aren't removing all members."],"tags":["update","workspace","lockfile","manifest"],"analyzedSha":"0e07a155371a6ce88ae53a2c00df940280c09a67","analyzedAt":"2026-08-06T01:46:58.334Z","schemaVersion":2}