{"record":{"id":"f65348695bf10328","repo":"BigPizzaV3/CodexPlusPlus","slug":"release-asset","errorCode":null,"errorMessage":"没有可下载的 Release asset","messagePattern":"没有可下载的 Release asset","errorType":"exception","errorClass":"anyhow::Error","httpStatus":null,"severity":"error","filePath":"crates/codex-plus-core/src/update.rs","lineNumber":205,"sourceCode":"    let update_available = is_newer_version(&release.version, current_version)?;\n    Ok(UpdateCheck {\n        current_version: current_version.to_string(),\n        latest_version: Some(release.version),\n        release_summary: release.body,\n        asset_name: release.asset_name,\n        asset_url: release.asset_url,\n        update_available,\n    })\n}\n\npub async fn perform_update(\n    release: &Release,\n    download_dir: &Path,\n) -> anyhow::Result<UpdateInstall> {\n    let url = release\n        .asset_url\n        .as_ref()\n        .ok_or_else(|| anyhow::anyhow!(\"没有可下载的 Release asset\"))?;\n    let _ = crate::diagnostic_log::append_diagnostic_log(\n        \"update.perform.start\",\n        json!({\n            \"version\": release.version,\n            \"assetName\": release.asset_name,\n            \"assetUrl\": url,\n            \"downloadTimeoutSeconds\": UPDATE_DOWNLOAD_TIMEOUT.as_secs()\n        }),\n    );\n    let response = match update_http_client()?.get(url).send().await {\n        Ok(response) => response,\n        Err(error) => {\n            let _ = crate::diagnostic_log::append_diagnostic_log(\n                \"update.download.failed\",\n                json!({ \"version\": release.version, \"assetName\": release.asset_name, \"error\": error.to_string() }),\n            );\n            return Err(anyhow::anyhow!(\"下载安装包失败：{error}\"));\n        }","sourceCodeStart":187,"sourceCodeEnd":223,"githubUrl":"https://github.com/BigPizzaV3/CodexPlusPlus/blob/1f431ae49b57b3055e0e6845ba6156c6b4232b4d/crates/codex-plus-core/src/update.rs#L187-L223","documentation":"perform_update requires a concrete download URL. release.asset_url is populated only when select_update_asset found an asset with platform_asset_rank < 2 (matching OS, native or cross arch) and non-empty name and URL; otherwise it is None and perform_update bails immediately with \"没有可下载的 Release asset\". The error therefore means: the release/manifest parsed fine, but nothing in its assets list matches the current platform.","triggerScenarios":"Running on Linux while the release only ships .dmg and .exe assets; a latest.json with an empty \"assets\" array; asset entries whose url/browser_download_url is blank (filtered out by select_update_asset); asset names that fail platform detection (macOS requires a name containing codex and plus, ending with .dmg).","commonSituations":"A user on a platform without published binaries clicking 'install update'; a release checked before its assets finished uploading; a CI manifest generator listing assets with empty URLs; renamed artifacts breaking platform-name detection.","solutions":["Verify the release actually contains an asset for your OS+arch with the expected naming (macOS: contains 'codex' and 'plus', ends with .dmg)","Re-run check_for_update to refresh the Release after assets were uploaded or fixed","If self-hosting latest.json, ensure every asset entry has non-empty name and url fields","On platforms without a matching asset, download the appropriate artifact manually instead of calling perform_update"],"exampleFix":"// before\nlet install = perform_update(&release, &dir).await?;\n\n// after\nif release.asset_url.is_none() {\n    anyhow::bail!(\n        \"no asset for this platform in release {} (selected asset: {:?})\",\n        release.version,\n        release.asset_name\n    );\n}\nlet install = perform_update(&release, &dir).await?;","handlingStrategy":"type-guard","validationCode":"if !has_downloadable_asset(&release) {\n    anyhow::bail!(\"no platform asset in release {} — download manually\", release.version);\n}\nlet install = perform_update(&release, &dir).await?;","typeGuard":"fn has_downloadable_asset(release: &codex_plus_core::update::Release) -> bool {\n    release.asset_url.as_deref().is_some_and(|u| !u.trim().is_empty())\n        && release.asset_name.as_deref().is_some_and(|n| !n.trim().is_empty())\n}","tryCatchPattern":null,"preventionTips":["Publish platform assets with names the selector recognizes (macOS: contains codex and plus, ends .dmg) before announcing a release","Refresh the update check right before installing so asset selection is current","Hide/disable the install action when UpdateCheck.asset_url is None"],"tags":["release-asset","platform-detection","update","download"],"backgroundTag":"no-matching-release-asset","analyzedSha":"1f431ae49b57b3055e0e6845ba6156c6b4232b4d","analyzedAt":"2026-08-16T20:54:18.598Z","schemaVersion":2},"datasetVersion":"2026-08-16T23:17:17.608Z"}