astrid-runtime/astrid · error
release has no asset list
Error message
release has no asset list
What it means
exact_asset_url looks up a named asset in a GitHub release JSON object. If the release payload has no 'assets' array (missing field or non-array), it throws this error. It guards against malformed or unexpected release responses before any asset matching happens.
Source
Thrown at crates/astrid-cli/src/commands/self_update/mod.rs:308
}
if method.manages_own_binary() {
return UpdatePlan::DeferToManager {
manager: method.label(),
how: method.upgrade_command(channel),
};
}
UpdatePlan::ApplyInPlace
}
/// Find exactly one release asset and return its browser download URL.
pub(super) fn exact_asset_url<'a>(
release: &'a serde_json::Value,
name: &str,
) -> anyhow::Result<&'a str> {
let assets = release
.get("assets")
.and_then(serde_json::Value::as_array)
.ok_or_else(|| anyhow::anyhow!("release has no asset list"))?;
anyhow::ensure!(
assets.len() <= MAX_RELEASE_ASSETS,
"release contains too many assets"
);
let mut matches = assets
.iter()
.filter(|asset| asset.get("name").and_then(|value| value.as_str()) == Some(name));
let asset = matches
.next()
.ok_or_else(|| anyhow::anyhow!("release has no asset '{name}'"))?;
anyhow::ensure!(
matches.next().is_none(),
"release contains duplicate asset '{name}'"
);
asset
.get("browser_download_url")
.and_then(|value| value.as_str())
.filter(|url| !url.is_empty())View on GitHub (pinned to affd8760f4)
Solutions
- Verify the fetched release is a real GitHub release JSON containing an 'assets' array (curl the releases/tag/<tag> endpoint).
- Check for GitHub API rate limiting (403 with rate-limit body) or auth problems and add a token if needed.
- Ensure the release has had its build artifacts uploaded; re-run the release workflow if assets are missing.
- Bypass any proxy/mirror that strips or reshapes the assets field.
Defensive patterns
Strategy: type-guard
Validate before calling
// before trusting the release payload
const release = JSON.parse(body);
if (!Array.isArray(release.assets)) throw new Error("response is not a release object"); Type guard
fn is_release_json(v: &serde_json::Value) -> bool {
v.get("assets").and_then(serde_json::Value::as_array).is_some()
} Try / catch
let assets = release.get("assets")
.and_then(serde_json::Value::as_array)
.ok_or_else(|| anyhow::anyhow!("release has no asset list"))
.with_context(|| format!("release payload: {}", release))?; Prevention
- Verify GitHub API responses (check HTTP status before parsing).
- Add a GitHub token to avoid rate-limit error bodies being parsed as releases.
- Don't query draft/prerelease tags that may lack assets.
When it happens
Trigger: fetch_release_by_tag or another release fetch returns JSON lacking an 'assets' array — e.g. a GitHub API error body, a draft release with no assets, or a proxy/mirror returning reshaped JSON — then any consumer (publisher_bundle_url, integrity_manifest_url, download_verify_extract, resolve_signed_channel, resolve_target_blake3) calls exact_asset_url.
Common situations: GitHub API rate-limit or error JSON being parsed as if it were a release; querying a draft/prerelease that has no assets uploaded yet; a corporate proxy that rewrites API responses.
Understand the failure class
Background: "invalid response format", "malformed payload", "missing data field": when an API returns 200 but the response shape is wrong — this error's family across 23 libraries.
Related errors
- release asset '{name}' has no download URL
- release contains too many assets
- release has no asset '{name}'
- release contains duplicate asset '{name}'
- release {resolved_ref} of {org}/{repo} ships no .capsule ass
AI-assisted analysis of astrid-runtime/astrid@affd8760f4 (2026-09-09).
Data as JSON: /api/errors/8a913b9303600bb6.
Report an issue: GitHub.