rust-lang/cargo · error

you can't generate a lockfile for an empty workspace.

Error message

you can't generate a lockfile for an empty workspace.

What it means

Thrown by `cargo update` when the workspace has zero members (`ws.members().count() == 0`). An empty workspace (only a virtual manifest with no member crates) has no dependencies to resolve, so Cargo cannot generate a meaningful lockfile.

Solutions

  1. Add at least one member crate to the workspace: list it under `members` in the root Cargo.toml.
  2. Run `cargo update` from inside a member crate's directory instead.
  3. Check that the `members` glob patterns actually match existing subdirectories.

Example fix

# Cargo.toml (before — empty workspace)
[workspace]
members = []

# After — add a member
[workspace]
members = ["my-crate"]
Defensive patterns

Strategy: validation

Validate before calling

fn workspace_has_members(ws: &cargo::core::Workspace) -> bool {
    ws.members().count() > 0
}

Prevention

When it happens

Trigger: Running `cargo update` in a directory whose `Cargo.toml` is a virtual manifest with an empty or missing `members` list, or where all members have been removed.

Common situations: Setting up a new workspace and running `cargo update` before adding any member crates; temporarily removing all members during a refactor; a misconfigured `members` glob that matches nothing.

Related errors


AI-assisted analysis of rust-lang/cargo@98a09e7e7d (2026-08-11). Data as JSON: /api/errors/2129f037e62f0f96. Report an issue: GitHub.

Appendix: source

Thrown at src/ops/cargo_update.rs:58

        &CliFeatures::new_all(true),
        HasDevUnits::Yes,
        previous_resolve,
        None,
        &[],
        true,
    )?;
    ops::write_pkg_lockfile(ws, &mut resolve)?;
    print_lockfile_changes(ws, previous_resolve, &resolve, &mut registry)?;
    Ok(())
}

pub fn update_lockfile(ws: &Workspace<'_>, opts: &UpdateOptions<'_>) -> CargoResult<()> {
    if opts.recursive && opts.precise.is_some() {
        anyhow::bail!("cannot specify both recursive and precise simultaneously")
    }

    if ws.members().count() == 0 {
        anyhow::bail!("you can't generate a lockfile for an empty workspace.")
    }

    // Updates often require a lot of modifications to the registry, so ensure
    // that we're synchronized against other Cargos.
    let _lock = ws
        .gctx()
        .acquire_package_cache_lock(CacheLockMode::DownloadExclusive)?;

    let previous_resolve = match ops::load_pkg_lockfile(ws)? {
        Some(resolve) => resolve,
        None => {
            match opts.precise {
                None => return generate_lockfile(ws),

                // Precise option specified, so calculate a previous_resolve required
                // by precise package update later.
                Some(_) => {
                    let mut registry = ws.package_registry()?;

View on GitHub (pinned to 98a09e7e7d)