{"record":{"id":"a41d8d8d5ada7d4f","repo":"windmill-labs/windmill","slug":"err-multipart-field-stream-error-converted-to-io","errorCode":null,"errorMessage":"err (multipart field stream error converted to io::Error during file upload)","messagePattern":"err \\(multipart field stream error converted to io::Error during file upload\\)","errorType":"exception","errorClass":"std::io::Error","httpStatus":null,"severity":"warning","filePath":"backend/windmill-api/src/args.rs","lineNumber":184,"sourceCode":"\n                        let file_key = get_random_file_name(ext);\n\n                        let options = Attributes::from_iter(vec![\n                            (Attribute::ContentType, content_type),\n                            (\n                                Attribute::ContentDisposition,\n                                if let Some(filename) = filename {\n                                    format!(\"inline; filename=\\\"{}\\\"\", filename)\n                                } else {\n                                    \"inline\".to_string()\n                                },\n                            ),\n                        ])\n                        .into();\n\n                        let bytes_stream = field\n                            .into_stream()\n                            .map_err(|err| std::io::Error::new(std::io::ErrorKind::Other, err));\n\n                        // file_key is always freshly random here, so this never\n                        // overwrites an existing object; the full size is the delta.\n                        #[cfg(not(feature = \"enterprise\"))]\n                        let max_size =\n                            Some(ce_storage_quota_remaining(db, w_id, None).await? as usize);\n                        #[cfg(feature = \"enterprise\")]\n                        let max_size: Option<usize> = None;\n\n                        match upload_file_internal(\n                            s3_client.clone(),\n                            &file_key,\n                            bytes_stream,\n                            options,\n                            max_size,\n                        )\n                        .await\n                        {","sourceCodeStart":166,"sourceCodeEnd":202,"githubUrl":"https://github.com/windmill-labs/windmill/blob/e474e8803ce2ff5c2df09a58dab51d45f5c922ca/backend/windmill-api/src/args.rs#L166-L202","documentation":"In `process_multipart`, an uploaded file's multipart field is consumed as a byte stream and piped into object storage. Any error yielded by the multipart field stream (malformed part, client disconnect mid-upload, decoder failure) is mapped into a `std::io::Error` of kind `Other` carrying the original error's string, and that io error then fails the upload request. The original reqwest/axum multipart error type is erased by the wrapping.","triggerScenarios":"A client aborts or resets the connection while streaming a file upload, the multipart body is truncated or malformed, or the field decoder errors partway through `field.into_stream()`.","commonSituations":"Large file uploads over flaky networks, browser cancellations, proxies cutting long uploads, malformed multipart boundaries from custom clients.","solutions":["Retry the upload from the client once the connection is stable; the error is usually a transient transport failure","Read the wrapped message inside the io error for the underlying multipart failure cause","Check intermediary proxies/timeouts for large uploads and raise body size/timeout limits","Test the upload with a standard client (curl/browser) to rule out malformed multipart encoding"],"exampleFix":null,"handlingStrategy":"retry","validationCode":null,"typeGuard":null,"tryCatchPattern":"try {\n  await uploadMultipart(file);\n} catch (e) {\n  if (e instanceof Error && /multipart|stream/i.test(e.message)) {\n    // transient transport failure — retry upload from the start\n  }\n}","preventionTips":["Use stable connections for large uploads; avoid flaky networks or raise timeouts","Set adequate body-size limits on proxies between client and server","Use standard HTTP clients to guarantee well-formed multipart bodies","Handle browser cancellations gracefully client-side"],"tags":["multipart","upload","io","streaming"],"backgroundTag":"stream-error-wrapped","analyzedSha":"e474e8803ce2ff5c2df09a58dab51d45f5c922ca","analyzedAt":"2026-09-03T12:38:19.024Z","contentChangedAt":"2026-09-03T12:38:19.024Z","schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}