{"record":{"id":"0e8ecf7d704911b0","repo":"xai-org/grok-build","slug":"blocking-write-task-panicked-e","errorCode":null,"errorMessage":"blocking write task panicked: {e}","messagePattern":"blocking write task panicked: (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/codegen/xai-grok-update/src/auto_update.rs","lineNumber":1213,"sourceCode":"    let mut buf = Vec::with_capacity((end - start + 1) as usize);\n    let mut stream = resp.bytes_stream();\n    while let Some(chunk) = stream.next().await {\n        let chunk = chunk?;\n        if let Some(pb) = progress {\n            pb.inc(chunk.len() as u64);\n        }\n        buf.extend_from_slice(&chunk);\n    }\n    let dest = dest.to_owned();\n    tokio::task::spawn_blocking(move || -> std::io::Result<()> {\n        use std::io::{Seek, SeekFrom, Write};\n        let mut f = std::fs::OpenOptions::new().write(true).open(&dest)?;\n        f.seek(SeekFrom::Start(start))?;\n        f.write_all(&buf)?;\n        Ok(())\n    })\n    .await\n    .map_err(|e| anyhow::anyhow!(\"blocking write task panicked: {e}\"))??;\n    Ok(())\n}\n\n/// Download a file from `url` to `dest` with a terminal progress bar.\n///\n/// If the server provides a `Content-Length` header, a determinate bar is shown\n/// with bytes downloaded, total size, and ETA. Otherwise a spinner with a byte\n/// counter is used as a fallback.\n#[doc(hidden)]\npub async fn download_with_progress(url: &str, dest: &std::path::Path) -> Result<()> {\n    // Try parallel byte-range first. Falls through to single-connection on any\n    // failure (HEAD missing Content-Length, ranges rejected, partial-fetch error).\n    match try_parallel_download(url, dest, true).await {\n        Ok(()) => return Ok(()),\n        Err(e) => {\n            tracing::debug!(\"parallel download failed, falling back to single connection: {e}\")\n        }\n    }","sourceCodeStart":1195,"sourceCodeEnd":1231,"githubUrl":"https://github.com/xai-org/grok-build/blob/bc7f02eddd3d84085849dc19ed216f11c23b0571/crates/codegen/xai-grok-update/src/auto_update.rs#L1195-L1231","documentation":"This error wraps a panic from the spawn_blocking task that writes a downloaded chunk to its byte range in the destination file. tokio converts a JoinError (panic or cancellation) from the blocking task into this anyhow error via map_err, so the actual write logic itself failed to run — it crashed. It means the file write worker died abnormally, not that the write returned an I/O error (those propagate via the ? before it).","triggerScenarios":"Calling download_range (indirectly through try_parallel_download) when the spawned blocking closure panics — e.g. seek/write_all panics, or an explicit panic/unwrap inside the blocking task. Also triggered if the blocking task was cancelled.","commonSituations":"Disk-full or permission errors surfacing as panics from unwraps in the write path; the destination file being closed/invalid while the task runs; thread cancellation during shutdown of a parallel download of a large artifact.","solutions":["Check the panic message embedded in {e} to find the real cause inside the blocking write closure","Verify the destination path is a writable, valid file and not removed concurrently","Re-run the download; parallel-range writes can race with file removal — ensure no other process deletes dest mid-download","Ensure the task is not being cancelled (process shutdown) mid-download"],"exampleFix":"// before\nlet mut f = std::fs::OpenOptions::new().write(true).open(&dest)?;\nf.seek(SeekFrom::Start(start))?;\nf.write_all(&buf)?;\n// after (avoid panicking inside the blocking task; return errors instead)\nlet mut f = std::fs::OpenOptions::new().write(true).open(&dest)\n    .map_err(|e| anyhow::anyhow!(\"open {} failed: {e}\", dest.display()))?;\nf.seek(SeekFrom::Start(start)).map_err(|e| anyhow::anyhow!(\"seek failed: {e}\"))?;\nf.write_all(&buf).map_err(|e| anyhow::anyhow!(\"write failed: {e}\"))?;","handlingStrategy":"try-catch","validationCode":"let meta = tokio::fs::metadata(&dest).await?;\nif !meta.is_file() { anyhow::bail!(\"dest is not a file: {}\", dest.display()); }","typeGuard":null,"tryCatchPattern":"match download_range(&url, &dest, start, end).await {\n    Err(e) if e.to_string().contains(\"blocking write task panicked\") => {\n        // inspect {e} for the inner panic, ensure dest is writable, retry once\n        eprintln!(\"download write panicked: {e}\");\n    }\n    Err(e) => return Err(e),\n    Ok(()) => {}\n}","preventionTips":["Ensure the destination file exists and is writable before starting parallel downloads","Never delete/replace dest while range downloads are in flight","Avoid panicking (unwrap/expect) inside blocking write closures; return Results","Check available disk space on large artifact downloads"],"tags":["tokio","io","panic","async"],"backgroundTag":"blocking-task-panicked","analyzedSha":"bc7f02eddd3d84085849dc19ed216f11c23b0571","analyzedAt":"2026-08-31T04:59:42.031Z","schemaVersion":2},"datasetVersion":"2026-08-31T09:17:48.483Z"}