{"record":{"id":"e6f51d9b6f6f1faf","repo":"cube-js/cube","slug":"could-not-parse-release-metadata-e","errorCode":null,"errorMessage":"could not parse release metadata: {e}","messagePattern":"could not parse release metadata: (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"rust/cube-cli/src/update.rs","lineNumber":79,"sourceCode":"/// Fetch the latest release metadata from the GitHub API.\npub async fn latest_release(http: &reqwest::Client) -> Result<Release> {\n    let url = format!(\n        \"{}/repos/{}/releases/latest\",\n        release_api_base(),\n        release_repo()\n    );\n    let res = http\n        .get(&url)\n        .header(reqwest::header::ACCEPT, \"application/vnd.github+json\")\n        .timeout(Duration::from_secs(10))\n        .send()\n        .await?;\n    if !res.status().is_success() {\n        bail!(\"release lookup failed ({}) at {url}\", res.status());\n    }\n    res.json::<Release>()\n        .await\n        .map_err(|e| anyhow!(\"could not parse release metadata: {e}\"))\n}\n\n/// Order-compare two dotted versions numerically, segment by segment.\nfn newer_than(candidate: &str, current: &str) -> bool {\n    let parse = |v: &str| -> Vec<u64> {\n        v.split(['.', '-'])\n            .map_while(|s| s.parse::<u64>().ok())\n            .collect()\n    };\n    let (a, b) = (parse(candidate), parse(current));\n    if a.is_empty() || b.is_empty() {\n        return candidate != current;\n    }\n    a > b\n}\n\n/// Outcome of the background release check.\n#[derive(Debug, Clone, PartialEq, Eq)]","sourceCodeStart":61,"sourceCodeEnd":97,"githubUrl":"https://github.com/cube-js/cube/blob/7d981676b36392fec34088b9afab6bdcad40207c/rust/cube-cli/src/update.rs#L61-L97","documentation":"In `latest_release`, after the GitHub release lookup succeeds, the JSON body is deserialized into the `Release` struct. If the response body isn't valid JSON or doesn't match the `Release` shape, the reqwest JSON error is wrapped as `could not parse release metadata: {e}`. This is a response-shape failure, not a network failure (non-2xx is handled earlier).","triggerScenarios":"`latest_release` fetches a release metadata URL that returns 2xx but with a body that fails `res.json::<Release>()`: HTML error pages behind proxies, changed/missing fields (e.g. tag name or assets) in the release JSON, or an empty body.","commonSituations":"Corporate proxy or captive portal returning 200 with HTML, GitHub API shape changes or a misconfigured update-manifest URL in self-hosted setups, running an old CLI against a renamed release feed.","solutions":["Check the wrapped reqwest/serde message (`{e}`) for the exact field that failed to deserialize.","Verify the release metadata URL returns the expected JSON (curl it and compare against the `Release` struct fields).","Rule out proxies returning HTML with a 200 status.","Update the CLI — an old `Release` struct may no longer match the current feed shape."],"exampleFix":"// before (body mismatch)\ncould not parse release metadata: missing field `tag_name`\n// after: verify feed\ncurl -s $RELEASE_URL | jq '.tag_name'","handlingStrategy":"try-catch","validationCode":"let body = res.text().await?;\nserde_json::from_str::<serde_json::Value>(&body)?; // pre-validate JSON shape\nif body.get(\"tag_name\").is_none() { /* abort before calling latest_release */ }","typeGuard":null,"tryCatchPattern":"match latest_release(url).await {\n    Err(e) if e.to_string().contains(\"could not parse release metadata\") => {\n        // inspect raw body / proxy behavior, fall back to current version\n    }\n    other => other?,\n}","preventionTips":["Verify the release feed URL returns JSON with a curl before wiring it in","Check for proxies/captive portals returning 200 + HTML","Keep the CLI updated so the Release struct matches the feed"],"tags":["network","json-parsing","versioning","cli"],"backgroundTag":"json-parse-failed","analyzedSha":"7d981676b36392fec34088b9afab6bdcad40207c","analyzedAt":"2026-09-02T03:45:10.400Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T15:18:49.778Z"}