{"id":"0f36bd938493e129","repo":"rust-lang/cargo","slug":"found-a-virtual-manifest-at-instead-of-a-pack","errorCode":null,"errorMessage":"found a virtual manifest at `{}` instead of a package manifest","messagePattern":"found a virtual manifest at `(.+?)` instead of a package manifest","errorType":"exception","errorClass":"anyhow::Error","httpStatus":null,"severity":"error","filePath":"src/ops/cargo_read_manifest.rs","lineNumber":22,"sourceCode":"use crate::util::errors::CargoResult;\nuse crate::workspace::parser::read_manifest;\nuse crate::workspace::{EitherManifest, Package, SourceId};\nuse tracing::trace;\n\npub fn read_package(\n    path: &Path,\n    source_id: SourceId,\n    gctx: &GlobalContext,\n) -> CargoResult<Package> {\n    trace!(\n        \"read_package; path={}; source-id={}\",\n        path.display(),\n        source_id\n    );\n    let manifest = read_manifest(path, source_id, gctx)?;\n    let manifest = match manifest {\n        EitherManifest::Real(manifest) => manifest,\n        EitherManifest::Virtual(..) => anyhow::bail!(\n            \"found a virtual manifest at `{}` instead of a package \\\n             manifest\",\n            path.display()\n        ),\n    };\n\n    Ok(Package::new(manifest, path))\n}\n","sourceCodeStart":4,"sourceCodeEnd":31,"githubUrl":"https://github.com/rust-lang/cargo/blob/0e07a155371a6ce88ae53a2c00df940280c09a67/src/ops/cargo_read_manifest.rs#L4-L31","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Target a specific member package with `-p <name>` or run the command from inside that member's directory.","If you intended a single-package project, replace the virtual manifest with a real one by adding a [package] section.","For programmatic callers, detect EitherManifest::Virtual before calling read_package and route to the workspace member list instead."],"exampleFix":"# before (virtual workspace root)\n$ cargo publish\nerror: found a virtual manifest at `./Cargo.toml`\n\n# after - publish a specific member\n$ cargo publish -p my-crate","handlingStrategy":"validation","validationCode":"# Detect a virtual manifest before calling package-level ops:\nif grep -qE '^\\[workspace\\]' Cargo.toml && ! grep -qE '^\\[package\\]' Cargo.toml; then\n  echo \"virtual manifest: target a member with -p <name>\" >&2\n  exit 1\nfi","typeGuard":null,"tryCatchPattern":null,"preventionTips":["When scripting against a workspace, enumerate members and target one with -p.","Do not assume the nearest Cargo.toml is a package manifest.","Prefer `cargo metadata --no-deps` to discover packages programmatically."],"tags":["manifest","workspace","virtual-manifest","packaging","publish"],"analyzedSha":"0e07a155371a6ce88ae53a2c00df940280c09a67","analyzedAt":"2026-08-06T01:46:58.334Z","schemaVersion":2}