{"record":{"id":"21aedb3c458e404b","repo":"hyperledger/fabric","slug":"form-does-not-contains-part-key-s","errorCode":null,"errorMessage":"form does not contains part key: %s","messagePattern":"form does not contains part key: (.+?)","errorType":"http","errorClass":null,"httpStatus":400,"severity":"warning","filePath":"orderer/common/channelparticipation/restapi.go","lineNumber":437,"sourceCode":"\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\n\t}\n\n\tblockBytes, err := io.ReadAll(file)\n\tif err != nil {\n\t\th.sendResponseJsonError(resp, http.StatusBadRequest, errors.Wrapf(err, \"cannot read file part %s from request body\", FormDataConfigBlockKey))","sourceCodeStart":419,"sourceCodeEnd":455,"githubUrl":"https://github.com/hyperledger/fabric/blob/2736b63f8fd5932511d56fe68b7039d15977f7f6/orderer/common/channelparticipation/restapi.go#L419-L455","documentation":"After successfully reading the multipart form, the handler requires a file part under the reserved key FormDataConfigBlockKey (\"config-block\"). If no such file part exists, the join request lacks the required config block and the handler returns 400 with this formatted error naming the expected key.","triggerScenarios":"serveJoin posting a multipart form without a file part named config-block — e.g. attaching the block under a different field name, sending it as a plain value field, or omitting the file entirely.","commonSituations":"Scripts using -F 'block=@...' instead of -F 'config-block=@...'; clients uploading the block as a text field rather than a file part; typos in the form key; sending only JSON metadata with no attachment.","solutions":["Attach the config block as a FILE part named exactly config-block: curl -F 'config-block=@path/to/genesis.block'","Ensure it is uploaded as a file part (binary), not a form value field","Check the client library's form field name matches FormDataConfigBlockKey (\"config-block\")","Read the %s in the server error message to confirm the expected key name"],"exampleFix":"// before\ncurl -X POST -F 'block=@genesis.block' http://orderer/participation/v2/channels?channelID=mychannel\n// after\ncurl -X POST -F 'config-block=@genesis.block' http://orderer/participation/v2/channels?channelID=mychannel","handlingStrategy":"validation","validationCode":"const FormDataConfigBlockKey = \"config-block\"\n// verify before sending:\nif _, err := os.Stat(configBlockPath); err != nil {\n\treturn fmt.Errorf(\"must attach a file part named %q\", FormDataConfigBlockKey)\n}","typeGuard":null,"tryCatchPattern":"if strings.Contains(err.Error(), \"form does not contains part key\") {\n\treturn fmt.Errorf(\"attach the block as a file part named exactly %q (curl -F 'config-block=@file')\", \"config-block\")\n}","preventionTips":["Always use the exact field name config-block for the file part","Upload the block as a binary file part, not a text value field","Centralize the join-request construction in one tested helper","Read the server's echoed key name in the error message to self-correct quickly"],"tags":["http","multipart","orderer","request-validation"],"backgroundTag":"required-form-field-missing","analyzedSha":"2736b63f8fd5932511d56fe68b7039d15977f7f6","analyzedAt":"2026-09-04T08:52:36.465Z","contentChangedAt":"2026-09-04T08:52:36.465Z","schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}