{"record":{"id":"4c7fa26001a78f4f","repo":"transact-rs/sqlx","slug":"invalid-cargo-metadata-output","errorCode":null,"errorMessage":"Invalid `cargo metadata` output","messagePattern":"Invalid `cargo metadata` output","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"sqlx-macros-core/src/query/metadata.rs","lineNumber":53,"sourceCode":"            use serde::Deserialize;\n            use std::process::Command;\n\n            let cargo = crate::env(\"CARGO\").unwrap();\n\n            let output = Command::new(cargo)\n                .args([\"metadata\", \"--format-version=1\", \"--no-deps\"])\n                .current_dir(&self.manifest_dir)\n                .env_remove(\"__CARGO_FIX_PLZ\")\n                .output()\n                .expect(\"Could not fetch metadata\");\n\n            #[derive(Deserialize)]\n            struct CargoMetadata {\n                workspace_root: PathBuf,\n            }\n\n            let metadata: CargoMetadata =\n                serde_json::from_slice(&output.stdout).expect(\"Invalid `cargo metadata` output\");\n\n            *root = Some(metadata.workspace_root);\n        }\n        root.clone().unwrap()\n    }\n}\n\npub fn try_for_crate() -> crate::Result<Arc<Metadata>> {\n    /// The `MtimeCache` in this type covers the config itself,\n    /// any changes to which will indirectly invalidate the loaded env vars as well.\n    #[expect(clippy::type_complexity)]\n    static METADATA: Mutex<\n        HashMap<String, Arc<MtimeCache<Arc<Metadata>>>, BuildHasherDefault<DefaultHasher>>,\n    > = Mutex::new(HashMap::with_hasher(BuildHasherDefault::new()));\n\n    let manifest_dir = crate::env(\"CARGO_MANIFEST_DIR\")?;\n\n    let cache = METADATA","sourceCodeStart":35,"sourceCodeEnd":71,"githubUrl":"https://github.com/transact-rs/sqlx/blob/03af8bcc5711a1935580a54bea249c219a0c217d/sqlx-macros-core/src/query/metadata.rs#L35-L71","documentation":"After `cargo metadata` runs, sqlx parses its stdout as JSON to extract `workspace_root`. This `.expect()` panics when `cargo metadata` produced output that is not valid JSON of the expected shape (e.g. the command emitted warnings/error text or an unexpected format version on stdout).","triggerScenarios":"Compiling with sqlx macros when `cargo metadata --format-version=1` stdout fails `serde_json::from_slice` — corrupted stderr/stdout mixing, custom cargo wrappers printing extra output, or a cargo version emitting an incompatible format.","commonSituations":"Wrapper scripts or cargo aliases that print banners to stdout; extremely old/new cargo with format drift; intercepted process output in unusual build environments.","solutions":["Run `cargo metadata --format-version=1 --no-deps` manually and verify stdout is pure JSON.","Remove cargo wrappers/aliases that add non-JSON output to stdout.","Update or align the toolchain (rustup update) so cargo's metadata format matches expectations.","Rebuild with `cargo clean` to rule out stale cached macro output."],"exampleFix":null,"handlingStrategy":"validation","validationCode":"// Verify stdout parses as JSON before relying on macro builds:\nlet out = std::process::Command::new(\"cargo\")\n    .args([\"metadata\", \"--format-version=1\", \"--no-deps\"]).output().unwrap();\nlet v: serde_json::Value = serde_json::from_slice(&out.stdout)\n    .expect(\"stdout is not valid JSON — check for cargo wrappers printing extra output\");\nassert!(v.get(\"workspace_root\").is_some());","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Remove cargo aliases/wrappers that print anything extra to stdout","Keep the Rust toolchain up to date so cargo metadata format matches","Run `cargo metadata --format-version=1 --no-deps | jq .workspace_root` as a sanity check"],"tags":["sqlx","macros","cargo-metadata","json","panic"],"backgroundTag":"cargo-metadata-failed","analyzedSha":"03af8bcc5711a1935580a54bea249c219a0c217d","analyzedAt":"2026-09-03T15:01:28.752Z","contentChangedAt":"2026-09-03T15:01:28.752Z","schemaVersion":2},"datasetVersion":"2026-09-10T17:17:09.494Z"}