cjpais/Handy · error · anyhow::Error
server sent more than the expected {} bytes
Error message
server sent more than the expected {} bytes What it means
Body-size cap enforcement: the server streamed past known_total (catalog-pinned size or advertised Content-Length). A server that overshoots its own contract is provably misbehaving, so the writer cuts the transfer at the first overflowing chunk, drops the file handle, and deletes everything written so far — preventing both disk-fill by an untrusted host and tainted data.
Source
Thrown at src-tauri/src/managers/model/download.rs:347
DOWNLOAD_STALL_TIMEOUT.as_secs()
)),
Ok(None) => break,
Ok(Some(chunk)) => chunk?,
},
_ = cancel_token.cancelled() => {
// Keep the partial for resume; caller handles state cleanup.
return Ok(HttpDownloadOutcome::Cancelled);
}
};
// An untrusted server must not be able to fill the disk: cut the
// transfer at the first byte past the known total instead of
// trusting it to eventually close the stream. Everything written
// so far is tainted by a provably-misbehaving server — clear it.
if let Some(cap) = known_total {
if downloaded + chunk.len() as u64 > cap {
drop(file);
let _ = fs::remove_file(partial_path);
return Err(anyhow::anyhow!(
"server sent more than the expected {} bytes",
cap
));
}
}
file.write_all(&chunk)?;
downloaded += chunk.len() as u64;
if last_emit.elapsed() >= throttle {
emit_progress(downloaded);
last_emit = Instant::now();
}
}
file.flush()?;
drop(file);
emit_progress(downloaded);
if let Some(expected) = known_total {
let actual = partial_path.metadata()?.len();View on GitHub (pinned to 98a4d80cce)
Solutions
- Refresh the catalog/app so expected_size matches the real object, then retry
- Verify the real size: curl -sI <url> and compare Content-Length against the catalog
- Switch to the official HuggingFace revision whose size is pinned
- Report or stop using a mirror that consistently overshoots
Defensive patterns
Strategy: retry
Try / catch
match downloader.download_http_resumable(...).await {
Ok(outcome) => Ok(outcome),
Err(e) if e.to_string().starts_with("server sent more than") => {
// server overshoots the pinned size: metadata is stale or the host is bad
refresh_catalog_or_switch_source(model_id).await?;
downloader.download_http_resumable(...).await
}
Err(e) => Err(e),
} Prevention
- Verify a mirror serves exactly the pinned byte size with curl -sI before adding it
- Pin sizes to immutable revisions so upstream re-publishes cannot overshoot
- Escalate recurring overshoot to a source switch rather than endless retries
When it happens
Trigger: Server sends an object larger than the pinned expected_size (upstream re-published a bigger file, stale catalog); server advertises a small Content-Length then streams more; a concatenating proxy.
Common situations: Catalog size skew after upstream updates; misconfigured mirrors serving bundles instead of single files.
Related errors
AI-assisted analysis of cjpais/Handy@98a4d80cce (2026-08-16).
Data as JSON: /api/errors/1e4eb633b0ac40d7.
Report an issue: GitHub.