{"record":{"id":"3ff6e4b39204ea67","repo":"rwf2/Rocket","slug":"other","errorCode":"Other","errorMessage":"spawn_block panic","messagePattern":"spawn_block panic","errorType":"exception","errorClass":"io::Error","httpStatus":null,"severity":"error","filePath":"core/lib/src/fs/temp_file.rs","lineNumber":521,"sourceCode":"        }\n    }\n\n    async fn from<'a>(\n        req: &Request<'_>,\n        data: Data<'_>,\n        file_name: Option<&'a FileName>,\n        content_type: Option<ContentType>,\n    ) -> io::Result<Capped<TempFile<'a>>> {\n        let limit = content_type.as_ref()\n            .and_then(|ct| ct.extension())\n            .and_then(|ext| req.limits().find([\"file\", ext.as_str()]))\n            .or_else(|| req.limits().get(\"file\"))\n            .unwrap_or(Limits::FILE);\n\n        let temp_dir = req.rocket().config().temp_dir.relative();\n        let file = task::spawn_blocking(move || NamedTempFile::new_in(temp_dir));\n        let file = file.await;\n        let file = file.map_err(|_| io::Error::new(io::ErrorKind::Other, \"spawn_block panic\"))??;\n        let (file, temp_path) = file.into_parts();\n\n        let mut file = File::from_std(file);\n        let fut = data.open(limit).stream_to(tokio::io::BufWriter::new(&mut file));\n        let n = fut.await;\n        let n = n?;\n        let temp_file = TempFile::File {\n            content_type, file_name,\n            path: Either::Left(temp_path),\n            len: n.written,\n        };\n\n        Ok(Capped::new(temp_file, n))\n    }\n}\n\n#[crate::async_trait]\nimpl<'v> FromFormField<'v> for Capped<TempFile<'v>> {","sourceCodeStart":503,"sourceCodeEnd":539,"githubUrl":"https://github.com/rwf2/Rocket/blob/3a54d079aef060a8f732bd04ea54b0581a604087/core/lib/src/fs/temp_file.rs#L503-L539","documentation":"Runtime io error while materializing an incoming multipart file part (TempFile::internal_from): creating the NamedTempFile happens inside task::spawn_blocking, and the JoinHandle returned a JoinError. Rocket maps it to io::ErrorKind::Other with message 'spawn_block panic'. In practice this is almost always the blocking task being cancelled at runtime shutdown rather than a literal panic in tempfile creation.","triggerScenarios":"A multipart upload with a file part arrives exactly as the server shuts down (grace period expires and the runtime cancels blocking tasks), so the spawn_blocking future is dropped/JoinError; also possible if the process is critically out of resources and the task panics.","commonSituations":"Deployments that recycle workers mid-upload (Kubernetes rolling updates, systemd restarts); load tests that shut servers down while uploads are in flight; very long uploads with a short shutdown.grace.","solutions":["Raise shutdown grace so uploads finish: Rocket.toml [default.shutdown] grace = 30, timeout is separate","Drain/stop accepting uploads before shutdown (e.g. readiness gate in orchestrators)","Check dmesg/logs for resource exhaustion if shutdown is not the cause","Retry the upload client-side on network error — this failure manifests to the client as a dropped connection"],"exampleFix":"# before\n# Rocket.toml (default grace = 5s, too short for slow uploads)\n\n# after\n# Rocket.toml\n[default.shutdown]\ngrace = 30\nctrlc = true\nsignals = [\"term\"]","handlingStrategy":"try-catch","validationCode":"// fail fast at startup if temp_dir is unusable, instead of per-request\n# use std::path::Path;\nfn temp_dir_ok(temp_dir: &Path) -> io::Result<()> {\n    std::fs::create_dir_all(temp_dir)?;\n    let probe = tempfile::Builder::new().prefix(\"probe\").tempfile_in(temp_dir)?;\n    drop(probe);\n    Ok(())\n}","typeGuard":null,"tryCatchPattern":"// in the handler; internal_from errors surface as a failed TempFile guard\n// register a catcher that distinguishes shutdown noise from real I/O failure\n#[catch(500)]\nfn internal(r: &Request) -> &'static str {\n    error_!(\"temp file creation failed (spawn_block panic?): {e:?}\", e = r.guard::<&std::io::Error>());\n    \"internal error\"\n}","preventionTips":["Set temp_dir to a writable, same-filesystem directory in Rocket.toml for production","Make shutdown.grace longer than max upload duration, and stop accepting uploads first","Clients should retry uploads that die mid-stream — this failure severs the connection"],"tags":["rust","rocket","tempfile","async","blocking-task","shutdown","multipart"],"backgroundTag":"blocking-task-panic","analyzedSha":"3a54d079aef060a8f732bd04ea54b0581a604087","analyzedAt":"2026-08-16T22:01:48.395Z","schemaVersion":2},"datasetVersion":"2026-08-16T23:17:17.608Z"}