{"record":{"id":"21084d0da7f00add","repo":"hyperledger/fabric","slug":"cannot-read-form-from-request-body","errorCode":null,"errorMessage":"cannot read form from request body","messagePattern":"cannot read form from request body","errorType":"http","errorClass":null,"httpStatus":400,"severity":"warning","filePath":"orderer/common/channelparticipation/restapi.go","lineNumber":432,"sourceCode":"\t\th.sendUpdateError(err, resp)\n\t\treturn\n\t}\n\tinfo.URL = path.Join(URLBaseV1Channels, info.Name)\n\n\th.logger.Debugf(\"Successfully update config channel: %s\", info.URL)\n\th.sendResponseCreated(resp, info.URL, info)\n}\n\n// Expect a multipart/form-data with a single part, of type file, with key FormDataConfigBlockKey.\nfunc (h *HTTPHandler) multipartFormDataBodyToBlock(params map[string]string, req *http.Request, resp http.ResponseWriter) *cb.Block {\n\tboundary := params[\"boundary\"]\n\treader := multipart.NewReader(\n\t\thttp.MaxBytesReader(resp, req.Body, int64(h.config.MaxRequestBodySize)),\n\t\tboundary,\n\t)\n\tform, err := reader.ReadForm(2 * int64(h.config.MaxRequestBodySize))\n\tif err != nil {\n\t\th.sendResponseJsonError(resp, http.StatusBadRequest, errors.Wrap(err, \"cannot read form from request body\"))\n\t\treturn nil\n\t}\n\n\tif _, exist := form.File[FormDataConfigBlockKey]; !exist {\n\t\th.sendResponseJsonError(resp, http.StatusBadRequest, errors.Errorf(\"form does not contains part key: %s\", FormDataConfigBlockKey))\n\t\treturn nil\n\t}\n\n\tif len(form.File) != 1 || len(form.Value) != 0 {\n\t\th.sendResponseJsonError(resp, http.StatusBadRequest, errors.New(\"form contains too many parts\"))\n\t\treturn nil\n\t}\n\n\tfileHeader := form.File[FormDataConfigBlockKey][0]\n\tfile, err := fileHeader.Open()\n\tif err != nil {\n\t\th.sendResponseJsonError(resp, http.StatusBadRequest, errors.Wrapf(err, \"cannot open file part %s from request body\", FormDataConfigBlockKey))\n\t\treturn nil","sourceCodeStart":414,"sourceCodeEnd":450,"githubUrl":"https://github.com/hyperledger/fabric/blob/2736b63f8fd5932511d56fe68b7039d15977f7f6/orderer/common/channelparticipation/restapi.go#L414-L450","documentation":"After determining the multipart boundary, multipartFormDataBodyToBlock streams the request body through multipart.Reader.ReadForm with a size cap of MaxRequestBodySize (body) and twice that for form memory. If the form cannot be parsed — malformed multipart syntax, truncated body, or body exceeding MaxBytesReader's limit — the handler returns 400 with this wrapped error.","triggerScenarios":"serveJoin receiving a body whose multipart encoding is invalid (wrong boundary, missing final boundary, truncated upload) or whose size exceeds orderer config channelParticipation.maxRequestBodySize, causing MaxBytesReader to cut the stream.","commonSituations":"Config block larger than MaxRequestBodySize (default 1MB) when joining a channel with a big config; network interruption during upload; client library generating a different boundary than advertised in the header; request body modified by middleware.","solutions":["Increase channelParticipation.maxRequestBodySize in orderer.yaml if the config block is large, and restart","Re-send with a correct multipart form (curl -F 'config-block=@genesis.block') so boundaries and parts are well-formed","Verify the uploaded config block file is complete and not truncated (compare checksums)","Check the wrapped inner error: http: request body too large means raise the size limit; multipart errors mean fix the body format"],"exampleFix":"// before (orderer.yaml)\nChannelParticipation:\n  MaxRequestBodySize: 1048576\n// after\nChannelParticipation:\n  MaxRequestBodySize: 10485760","handlingStrategy":"try-catch","validationCode":"fi, _ := os.Stat(configBlockPath)\nif fi.Size() > maxRequestBodySize {\n\treturn fmt.Errorf(\"config block is %d bytes; raise channelParticipation.maxRequestBodySize (current %d)\", fi.Size(), maxRequestBodySize)\n}","typeGuard":null,"tryCatchPattern":"if err != nil && strings.Contains(err.Error(), \"cannot read form from request body\") {\n\tif strings.Contains(err.Error(), \"request body too large\") {\n\t\t// raise ChannelParticipation.MaxRequestBodySize in orderer.yaml\n\t} else {\n\t\t// malformed multipart: rebuild with curl -F / multipart writer\n\t}\n}","preventionTips":["Size maxRequestBodySize above your largest expected config block","Upload complete, checksum-verified block files","Use standard multipart writers instead of hand-built bodies","Avoid middleware that buffers/truncates request bodies"],"tags":["http","multipart","request-body","orderer"],"backgroundTag":"multipart-form-parse-failed","analyzedSha":"2736b63f8fd5932511d56fe68b7039d15977f7f6","analyzedAt":"2026-09-04T08:52:36.465Z","contentChangedAt":"2026-09-04T08:52:36.465Z","schemaVersion":2},"datasetVersion":"2026-09-08T15:18:49.778Z"}