tonhowtf/omniget · error · anyhow::Error

Failed to read thumbnail

Error message

Failed to read thumbnail: {}

What it means

After a successful HTTP response, download_thumbnail reads the full response body as bytes. If reading the body fails (connection dropped mid-transfer, timeout while streaming body, decompression error), the reqwest error is wrapped with this message. The status was OK but the payload never arrived intact.

Solutions

  1. Retry the download once or twice; transient body read failures are common.
  2. Increase the client's read/total timeout if thumbnails are large or the network is slow.
  3. Check that no intermediary (proxy/VPN/firewall) is truncating responses.
  4. Fall back to skipping the thumbnail embed instead of failing the whole download.

Example fix

// before
let bytes = response.bytes().await
    .map_err(|e| anyhow!("Failed to read thumbnail: {}", e))?;
// after
let bytes = match response.bytes().await {
    Ok(b) => b,
    Err(e) => {
        log::warn!("thumbnail body read failed: {e}");
        return Ok(None);
    }
};
Defensive patterns

Strategy: retry

Validate before calling

// Check Content-Length availability before reading
let expected = response.content_length();
if expected == Some(0) { return Ok(None); }

Try / catch

let bytes = response.bytes().await
    .or_else(|_| async { client.get(url).send().await?.bytes().await }) // one retry
    .await
    .map_err(|e| { log::warn!("thumb body failed: {e}"); e })?;

Prevention

When it happens

Trigger: resp.bytes().await fails because the server closed the connection mid-body, a read timeout expired, or the response stream errored.

Common situations: Flaky mobile/proxied networks; CDN aborting large responses; keep-alive connections reset by intermediaries; server-side timeouts on slow clients.

Related errors


AI-assisted analysis of tonhowtf/omniget@8600b91f42 (2026-09-12). Data as JSON: /api/errors/86f17f94b5b4e842. Report an issue: GitHub.

Appendix: source

Thrown at src-tauri/omniget-core/src/core/ffmpeg.rs:591

    dest_dir: &Path,
) -> anyhow::Result<std::path::PathBuf> {
    let response = client
        .get(url)
        .send()
        .await
        .map_err(|e| anyhow!("Failed to download thumbnail: {}", e))?;

    let content_type = response
        .headers()
        .get("content-type")
        .and_then(|v| v.to_str().ok())
        .unwrap_or("image/jpeg")
        .to_string();

    let bytes = response
        .bytes()
        .await
        .map_err(|e| anyhow!("Failed to read thumbnail: {}", e))?;

    let ext = if content_type.contains("png") {
        "png"
    } else {
        "jpg"
    };

    let thumb_path = dest_dir.join(format!(".omniget_thumb_{}.{}", uuid::Uuid::new_v4(), ext));
    std::fs::write(&thumb_path, &bytes)?;

    if ext == "png" {
        let jpg_path = dest_dir.join(format!(".omniget_thumb_{}.jpg", uuid::Uuid::new_v4()));
        let convert_result = crate::core::process::command("ffmpeg")
            .args([
                "-y",
                "-i",
                &thumb_path.to_string_lossy(),
                &jpg_path.to_string_lossy(),

View on GitHub (pinned to 8600b91f42)