BigPizzaV3/CodexPlusPlus · error · anyhow::Error
latest.json missing version
Error message
latest.json missing version
What it means
release_from_latest_json_payload parses the app's own latest.json update manifest. The version is read from payload.get("version").or_else(payload.get("tag_name")) and must be a JSON string; if neither key exists or neither is a string, it bails with "latest.json missing version". This runs inside fetch_latest_release / check_for_update, so a malformed manifest fails the whole update check.
Source
Thrown at crates/codex-plus-core/src/update.rs:114
.and_then(Value::as_str)
.unwrap_or_default()
.to_string(),
body: payload
.get("body")
.and_then(Value::as_str)
.unwrap_or_default()
.to_string(),
asset_name: selected.as_ref().map(|asset| asset.name.clone()),
asset_url: selected.map(|asset| asset.browser_download_url),
})
}
pub fn release_from_latest_json_payload(payload: &Value) -> anyhow::Result<Release> {
let version = payload
.get("version")
.or_else(|| payload.get("tag_name"))
.and_then(Value::as_str)
.ok_or_else(|| anyhow::anyhow!("latest.json missing version"))?
.to_string();
let assets = payload
.get("assets")
.and_then(Value::as_array)
.into_iter()
.flatten()
.filter_map(|asset| {
let name = asset.get("name")?.as_str()?.to_string();
let url = asset
.get("url")
.or_else(|| asset.get("browser_download_url"))?
.as_str()?
.to_string();
Some((name, url))
})
.collect::<Vec<_>>();
let selected = select_update_asset(&assets);
Ok(Release {View on GitHub (pinned to 1f431ae49b)
Solutions
- Open the manifest URL (DEFAULT_LATEST_JSON_URL or your configured one) with curl and inspect the body
- Add a top-level "version": "x.y.z" string (or "tag_name") to latest.json
- If the version is emitted as a JSON number, quote it in the generator
- Re-run check_for_update after republishing the manifest
Example fix
// before (latest.json)
{ "pub_date": "2026-08-16T00:00:00Z", "platforms": { ... } }
// after
{ "version": "1.4.2", "pub_date": "2026-08-16T00:00:00Z", "platforms": { ... } } Defensive patterns
Strategy: type-guard
Validate before calling
if !latest_json_has_version(&payload) {
anyhow::bail!("latest.json lacks a usable version: {payload}");
}
let release = release_from_latest_json_payload(&payload)?; Type guard
fn latest_json_has_version(payload: &serde_json::Value) -> bool {
payload
.get("version")
.or_else(|| payload.get("tag_name"))
.and_then(serde_json::Value::as_str)
.is_some_and(|v| !v.trim().is_empty())
} Prevention
- Validate the manifest shape in the publishing pipeline before it goes live
- Keep manifest generators in the same repo as a schema check in CI
- Quote versions as strings in generated JSON
When it happens
Trigger: A latest.json that only has {"pub_date": ..., "platforms": {...}} (Tauri-style manifest) with no top-level version; a manifest where the version is a JSON number ({"version": 12}) instead of a string; a typo'd key like "Version" or "ver".
Common situations: Migrating between updater manifest conventions; a CI manifest generator whose version variable is empty so the key is omitted; hand-edited manifests; publishing the version as a number.
Related errors
- {} must be a JSON object
- auth.json 必须是 JSON 对象
- Invalid version tag: {value}
- release payload missing tag_name
AI-assisted analysis of BigPizzaV3/CodexPlusPlus@1f431ae49b (2026-08-16).
Data as JSON: /api/errors/3d79518e018c2aa6.
Report an issue: GitHub.