BoundaryML/baml · error
No download URL for asset
Error message
No download URL for asset
What it means
After finding the matching asset, get_playground_dist reads asset["browser_download_url"].as_str(). If the asset object lacks that field (or it isn't a string), this error is returned. A GitHub release asset should always carry browser_download_url, so this indicates a malformed or unexpected asset object.
Source
Thrown at engine/playground-server/src/server.rs:168
}
tracing::info!("Parsing JSON response...");
let release: serde_json::Value = resp
.json()
.await
.map_err(|e| anyhow::anyhow!("Failed to parse JSON response: {e}"))?;
// Find the main asset
let assets = release["assets"]
.as_array()
.ok_or_else(|| anyhow::anyhow!("No assets in release metadata"))?;
let asset = assets
.iter()
.find(|a| a["name"].as_str() == Some(&web_panel_asset_name))
.ok_or_else(|| anyhow::anyhow!("No asset named '{}' in release", web_panel_asset_name))?;
let download_url = asset["browser_download_url"]
.as_str()
.ok_or_else(|| anyhow::anyhow!("No download URL for asset"))?;
// Find the checksum asset
let checksum_asset = assets
.iter()
.find(|a| a["name"].as_str() == Some(&checksum_asset_name))
.ok_or_else(|| {
anyhow::anyhow!(
"No checksum asset named '{}' in release",
checksum_asset_name
)
})?;
let checksum_url = checksum_asset["browser_download_url"]
.as_str()
.ok_or_else(|| anyhow::anyhow!("No download URL for checksum asset"))?;
tracing::info!(
"Found assets - main: {}, checksum: {}",
download_url,View on GitHub (pinned to bd85ce9dee)
Solutions
- Inspect the asset JSON and confirm browser_download_url is present; fix the mocked/intermediary payload if it is synthetic.
- Use the html_url/upload URL to reconstruct the download URL as a fallback if the field is genuinely absent.
- Update parsing code if the GitHub API schema changed.
Defensive patterns
Strategy: validation
Validate before calling
// preflight: confirm asset objects carry browser_download_url
let v: serde_json::Value = reqwest::get(&api_url).await?.json().await?;
let ok = v["assets"].as_array().map_or(false, |a| {
a.iter().all(|x| x["browser_download_url"].is_string())
});
if !ok { eprintln!("Release payload missing browser_download_url fields"); } Type guard
fn download_url<'a>(asset: &'a serde_json::Value) -> Option<&'a str> {
asset["browser_download_url"].as_str()
} Try / catch
match get_playground_dist().await {
Err(e) if e.to_string().contains("No download URL for asset") => {
eprintln!("Malformed asset payload — inspect the GitHub API response");
}
other => other?,
} Prevention
- Use real GitHub API responses (not hand-made mocks missing fields)
- Validate asset JSON shape in tests
- Reconstruct URLs from asset IDs as fallback
When it happens
Trigger: The matched asset JSON has no string browser_download_url field — e.g. hand-crafted/mock release metadata, or an unexpected API payload shape.
Common situations: Testing against mocked GitHub API responses missing fields; a GitHub API payload change; proxy-injected JSON that drops fields.
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
- No assets in release metadata
- No download URL for checksum asset
- Failed to parse JSON response: {e}
- `{BAML_JSON_JSON}` is declared by the stdlib
- Failed to deserialize value: {e}
AI-assisted analysis of BoundaryML/baml@bd85ce9dee (2026-09-12).
Data as JSON: /api/errors/6fcc991d5a5ea25f.
Report an issue: GitHub.