{"record":{"id":"3f5786cb018f7c4d","repo":"argoproj/argo-workflows","slug":"failed-to-parse-multipart-form","errorCode":null,"errorMessage":"Failed to parse multipart form: ","messagePattern":"Failed to parse multipart form: ","errorType":"http","errorClass":null,"httpStatus":400,"severity":"warning","filePath":"server/artifacts/artifact_server.go","lineNumber":168,"sourceCode":"\t}\n\tr.Body = http.MaxBytesReader(w, r.Body, int64(maxUploadBytes))\n\n\t// mime/multipart.ReadForm already removes temp files on parse error, but\n\t// registering cleanup here makes the handler's correctness independent of\n\t// that stdlib internal — any future error return still frees temp files.\n\tdefer func() {\n\t\tif r.MultipartForm != nil {\n\t\t\t_ = r.MultipartForm.RemoveAll()\n\t\t}\n\t}()\n\n\t// Parse multipart form (max 32MB in memory, rest on disk)\n\tif parseErr := r.ParseMultipartForm(32 << 20); parseErr != nil {\n\t\tif _, ok := errors.AsType[*http.MaxBytesError](parseErr); ok {\n\t\t\thttp.Error(w, http.StatusText(http.StatusRequestEntityTooLarge), http.StatusRequestEntityTooLarge)\n\t\t\treturn\n\t\t}\n\t\thttp.Error(w, \"Failed to parse multipart form: \"+parseErr.Error(), http.StatusBadRequest)\n\t\treturn\n\t}\n\n\tfile, header, err := r.FormFile(\"file\")\n\tif err != nil {\n\t\thttp.Error(w, \"Failed to get file from form: \"+err.Error(), http.StatusBadRequest)\n\t\treturn\n\t}\n\tdefer file.Close()\n\n\ta.logger.WithFields(logging.Fields{\n\t\t\"filename\": header.Filename,\n\t\t\"size\":     header.Size,\n\t}).Info(ctx, \"Received file for upload\")\n\n\t// Find the artifact in the WorkflowTemplate's arguments.artifacts\n\tvar templateArtifact *wfv1.Artifact\n\tif wfTemplate.Spec.Arguments.Artifacts != nil {","sourceCodeStart":150,"sourceCodeEnd":186,"githubUrl":"https://github.com/argoproj/argo-workflows/blob/35bff19146f5a6ada77468c431f2624bd577e373/server/artifacts/artifact_server.go#L150-L186","documentation":"r.ParseMultipartForm(32<<20) buffers up to 32MB in memory and spills the rest to disk; failures that are NOT MaxBytesError (e.g. malformed multipart body, wrong Content-Type, truncated stream) return 400 with 'Failed to parse multipart form: <detail>'. The message in this error index shows the prefix that gets the underlying error appended.","triggerScenarios":"Posting a body with Content-Type other than multipart/form-data (e.g. application/octet-stream, raw binary); corrupted or truncated multipart stream; missing boundary in Content-Type header; proxies that alter the body.","commonSituations":"Clients using -d or --data-binary instead of -F with curl; HTTP libraries posting fields without multipart encoding; request aborted mid-upload leaving an incomplete body; ingress gateways buffering incorrectly.","solutions":["Send a proper multipart/form-data body: curl -F 'file=@path' (not -d/--data-binary)","Ensure the Content-Type header includes the multipart boundary (let the HTTP client set it automatically)","Retry the upload if the connection was interrupted/truncated","Check for intermediaries (ingress, service mesh) modifying or buffering the request body"],"exampleFix":"# before (raw body, not multipart)\ncurl -X POST --data-binary @data.bin https://.../upload-artifacts/ns/tmpl/art\n# after\ncurl -X POST -F 'file=@data.bin' https://.../upload-artifacts/ns/tmpl/art","handlingStrategy":"validation","validationCode":"ct := req.Header.Get(\"Content-Type\")\nif !strings.HasPrefix(ct, \"multipart/form-data\") {\n    return fmt.Errorf(\"must POST multipart/form-data with a 'file' field, got %s\", ct)\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Use -F/--form with curl or the HTTP client's multipart writer; never --data-binary","Let the HTTP client set Content-Type so the boundary is included","Retry on network interruption to avoid truncated bodies","Verify proxies/mesh do not re-encode request bodies"],"tags":["http-400","multipart","upload","http"],"backgroundTag":"malformed-multipart-body","analyzedSha":"35bff19146f5a6ada77468c431f2624bd577e373","analyzedAt":"2026-09-03T19:34:35.908Z","contentChangedAt":"2026-09-03T19:34:35.908Z","schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}