bevyengine/bevy · critical

Unable to read cargo manifest: {}

Error message

Unable to read cargo manifest: {}

What it means

bevy_macro_utils' BevyManifest::read_manifest panics when Cargo.toml at the derived CARGO_MANIFEST_DIR path cannot be read (crates/bevy_macro_utils/src/bevy_manifest.rs:76). Bevy proc macros use this at compile time to resolve sibling crate paths, so the panic aborts compilation of any crate expanding Bevy macros.

Source

Thrown at crates/bevy_macro_utils/src/bevy_manifest.rs:76

                assert!(
                    path.exists(),
                    "Cargo manifest does not exist at path {}",
                    path.display()
                );
                path
            })
            .expect("CARGO_MANIFEST_DIR is not defined.")
    }

    fn get_manifest_modified_time(
        cargo_manifest_path: &Path,
    ) -> Result<SystemTime, std::io::Error> {
        std::fs::metadata(cargo_manifest_path).and_then(|metadata| metadata.modified())
    }

    fn read_manifest(path: &Path) -> Document<Box<str>> {
        let manifest = std::fs::read_to_string(path)
            .unwrap_or_else(|_| panic!("Unable to read cargo manifest: {}", path.display()))
            .into_boxed_str();
        Document::parse(manifest)
            .unwrap_or_else(|_| panic!("Failed to parse cargo manifest: {}", path.display()))
    }

    /// Attempt to retrieve the [path](syn::Path) of a particular package in
    /// the [manifest](BevyManifest) by [name](str).
    pub fn maybe_get_path(&self, name: &str) -> Option<syn::Path> {
        // Cargo normalizes hyphens to underscores when crates are referenced from Rust code.
        let rust_name = name.replace('-', "_");
        let find_in_deps = |deps: &Item| -> Option<syn::Path> {
            let package = if deps.get(name).is_some() {
                return Some(Self::parse_str(&rust_name));
            } else if deps.get(BEVY).is_some() {
                BEVY
            } else {
                // Note: to support bevy crate aliases, we could do scanning here to find a crate with a "package" name that
                // matches our request, but that would then mean we are scanning every dependency (and dev dependency) for every

View on GitHub (pinned to 396ca72708)

Solutions

  1. Run cargo clean and rebuild from a quiescent, unmodified source tree.
  2. Verify Cargo.toml exists and is readable in the failing crate's directory (check the path printed in the panic).
  3. Allowlist the project in antivirus/sandbox tools or move off flaky network filesystems so the manifest cannot be locked or disappear during macro expansion.

Example fix

// before: cargo build fails with 'Unable to read cargo manifest: .../Cargo.toml'

// after
cargo clean
cargo build # rebuild with no concurrent edits to the source tree
Defensive patterns

Strategy: retry

Validate before calling

# pre-build sanity check (CI or wrapper script):
test -f "${CARGO_MANIFEST_DIR:-.}/Cargo.toml" || {
  echo "Cargo.toml missing/unreadable; restore sources before building"; exit 1;
}

Prevention

When it happens

Trigger: Compiling a crate that uses Bevy macros while its Cargo.toml is missing or unreadable mid-build: interrupted builds, sources moved/deleted during compile, sandbox/permission/antivirus locks on the manifest, or a corrupted target cache pointing at stale paths.

Common situations: CI cache corruption; builds on network filesystems where the manifest briefly vanishes; antivirus or sandbox tooling locking Cargo.toml; editing or moving files while cargo runs; unusual workspaces with generated manifests.

Related errors


AI-assisted analysis of bevyengine/bevy@396ca72708 (2026-08-20). Data as JSON: /api/errors/1baa425b04b41492. Report an issue: GitHub.