zeroclaw-labs/zeroclaw · error
HTTP {} downloading datasheet from {url}
Error message
HTTP {} downloading datasheet from {url} What it means
`download_datasheet` GETs a component datasheet URL with reqwest (30s timeout, ZeroClaw user agent) and bails on any non-2xx status, embedding the HTTP status and URL. The status code is the diagnosis: 404 means the datasheet moved or the URL is wrong, 403 usually means bot/hotlink blocking, 5xx means vendor-side outage. DNS and timeout failures surface as different errors from `send()`, so this one is strictly an HTTP response status problem.
Source
Thrown at crates/zeroclaw-hardware/src/datasheet.rs:70
/// Returns the path to the saved file.
pub async fn download_datasheet(
&self,
url: &str,
device_name: &str,
) -> anyhow::Result<PathBuf> {
std::fs::create_dir_all(&self.datasheet_dir)?;
let filename = format!("{}.pdf", device_name.to_lowercase().replace(' ', "_"));
let dest = self.datasheet_dir.join(&filename);
let client = reqwest::Client::builder()
.user_agent("ZeroClaw/0.1 (datasheet downloader)")
.timeout(std::time::Duration::from_secs(30))
.build()?;
let response = client.get(url).send().await?;
if !response.status().is_success() {
anyhow::bail!(
"HTTP {} downloading datasheet from {url}",
response.status()
);
}
let bytes = response.bytes().await?;
std::fs::write(&dest, &bytes)?;
::zeroclaw_log::record!(
INFO,
::zeroclaw_log::Event::new(module_path!(), ::zeroclaw_log::Action::Note).with_attrs(
::serde_json::json!({"device": device_name, "path": dest.display().to_string()})
),
"datasheet downloaded"
);
Ok(dest)
}
/// List all locally cached datasheet filenames.View on GitHub (pinned to 88bb9c8533)
Solutions
- Read the status in the message: for 404, find the datasheet's current URL on the vendor's product page and update the tool input
- For 403, download the file manually in a browser and point the tool at a local or mirrored copy
- Retry later for 5xx — the outage is on the vendor's side
Example fix
// before
download_datasheet("https://vendor.com/old/lm741.pdf").await?;
// after — canonical URL from the vendor's current product page
download_datasheet("https://www.ti.com/lit/ds/symlink/lm741.pdf").await?; Defensive patterns
Strategy: retry
Validate before calling
// Pre-flight the URL cheaply before downloading:
let resp = client.head(url).send().await?;
if !resp.status().is_success() {
anyhow::bail!("datasheet URL unreachable ({}): {url}", resp.status());
} Try / catch
let mut attempt = 0;
loop {
match download_datasheet(url, &dest).await {
Ok(_) => break,
Err(e) if attempt < 2 && e.to_string().contains("HTTP 5") => {
attempt += 1;
tokio::time::sleep(std::time::Duration::from_secs(2u64.pow(attempt))).await;
}
Err(e) => return Err(e), // 404/403 are permanent — do not retry
}
} Prevention
- Pin canonical vendor datasheet URLs (the /lit/ds/ style links) instead of search-result URLs
- Mirror frequently used datasheets locally so vendor outages and bot blocks cannot break runs
- Check the embedded HTTP status first: 4xx is permanent, 5xx and timeouts are retryable
When it happens
Trigger: Executing the datasheet tool with a vendor URL that 404s after the manufacturer reorganized their site; a 403 from portals that block non-browser user agents; 5xx during vendor downtime.
Common situations: Stale hardcoded datasheet URLs in tool configuration; datasheet portals behind bot protection; typos in the URL handed to the tool.
Related errors
- audio download failed: {}
- audio download failed ({status}) for message {message_id}
- attachment download failed ({status}): {body}
- WeCom attachment download failed: kind={} msg_id={} url_targ
- elicitation returned unknown choice const: {s}
AI-assisted analysis of zeroclaw-labs/zeroclaw@88bb9c8533 (2026-08-23).
Data as JSON: /api/errors/4ad9e45980552963.
Report an issue: GitHub.