rust-lang/cargo · error · anyhow::Error

found a virtual manifest at `{}` instead of a package manife

Error message

found a virtual manifest at `{}` instead of a package manifest

What it means

read_package expects a Cargo.toml containing a [package] table (a Real manifest). When it parses a virtual manifest — one that only declares [workspace] with no package — it cannot produce a Package, so it bails at cargo_read_manifest.rs:22. Virtual manifests describe a workspace root but are not themselves buildable/publishable.

Source

Thrown at src/ops/cargo_read_manifest.rs:22

use crate::util::errors::CargoResult;
use crate::workspace::parser::read_manifest;
use crate::workspace::{EitherManifest, Package, SourceId};
use tracing::trace;

pub fn read_package(
    path: &Path,
    source_id: SourceId,
    gctx: &GlobalContext,
) -> CargoResult<Package> {
    trace!(
        "read_package; path={}; source-id={}",
        path.display(),
        source_id
    );
    let manifest = read_manifest(path, source_id, gctx)?;
    let manifest = match manifest {
        EitherManifest::Real(manifest) => manifest,
        EitherManifest::Virtual(..) => anyhow::bail!(
            "found a virtual manifest at `{}` instead of a package \
             manifest",
            path.display()
        ),
    };

    Ok(Package::new(manifest, path))
}

View on GitHub (pinned to 0e07a15537)

Solutions

  1. Target a specific member package with `-p <name>` or run the command from inside that member's directory.
  2. If you intended a single-package project, replace the virtual manifest with a real one by adding a [package] section.
  3. For programmatic callers, detect EitherManifest::Virtual before calling read_package and route to the workspace member list instead.

Example fix

# before (virtual workspace root)
$ cargo publish
error: found a virtual manifest at `./Cargo.toml`

# after - publish a specific member
$ cargo publish -p my-crate
Defensive patterns

Strategy: validation

Validate before calling

# Detect a virtual manifest before calling package-level ops:
if grep -qE '^\[workspace\]' Cargo.toml && ! grep -qE '^\[package\]' Cargo.toml; then
  echo "virtual manifest: target a member with -p <name>" >&2
  exit 1
fi

Prevention

When it happens

Trigger: Pointing a package-level operation (read_package, used by cargo package/publish/registry flows) at the workspace-root Cargo.toml of a multi-crate workspace that is virtual.

Common situations: Running `cargo publish` (without -p) at the root of a virtual workspace; tooling that walks up to the nearest Cargo.toml and assumes it is a package.

Related errors


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