hyperledger/fabric · warning
form does not contains part key: %s
Error message
form does not contains part key: %s
What it means
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.
Source
Thrown at orderer/common/channelparticipation/restapi.go:437
h.logger.Debugf("Successfully update config channel: %s", info.URL)
h.sendResponseCreated(resp, info.URL, info)
}
// Expect a multipart/form-data with a single part, of type file, with key FormDataConfigBlockKey.
func (h *HTTPHandler) multipartFormDataBodyToBlock(params map[string]string, req *http.Request, resp http.ResponseWriter) *cb.Block {
boundary := params["boundary"]
reader := multipart.NewReader(
http.MaxBytesReader(resp, req.Body, int64(h.config.MaxRequestBodySize)),
boundary,
)
form, err := reader.ReadForm(2 * int64(h.config.MaxRequestBodySize))
if err != nil {
h.sendResponseJsonError(resp, http.StatusBadRequest, errors.Wrap(err, "cannot read form from request body"))
return nil
}
if _, exist := form.File[FormDataConfigBlockKey]; !exist {
h.sendResponseJsonError(resp, http.StatusBadRequest, errors.Errorf("form does not contains part key: %s", FormDataConfigBlockKey))
return nil
}
if len(form.File) != 1 || len(form.Value) != 0 {
h.sendResponseJsonError(resp, http.StatusBadRequest, errors.New("form contains too many parts"))
return nil
}
fileHeader := form.File[FormDataConfigBlockKey][0]
file, err := fileHeader.Open()
if err != nil {
h.sendResponseJsonError(resp, http.StatusBadRequest, errors.Wrapf(err, "cannot open file part %s from request body", FormDataConfigBlockKey))
return nil
}
blockBytes, err := io.ReadAll(file)
if err != nil {
h.sendResponseJsonError(resp, http.StatusBadRequest, errors.Wrapf(err, "cannot read file part %s from request body", FormDataConfigBlockKey))View on GitHub (pinned to 2736b63f8f)
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
Example fix
// before curl -X POST -F 'block=@genesis.block' http://orderer/participation/v2/channels?channelID=mychannel // after curl -X POST -F 'config-block=@genesis.block' http://orderer/participation/v2/channels?channelID=mychannel
Defensive patterns
Strategy: validation
Validate before calling
const FormDataConfigBlockKey = "config-block"
// verify before sending:
if _, err := os.Stat(configBlockPath); err != nil {
return fmt.Errorf("must attach a file part named %q", FormDataConfigBlockKey)
} Try / catch
if strings.Contains(err.Error(), "form does not contains part key") {
return fmt.Errorf("attach the block as a file part named exactly %q (curl -F 'config-block=@file')", "config-block")
} Prevention
- 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
When it happens
Trigger: 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.
Common situations: 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.
Related errors
- cannot parse Mime media type
- cannot read form from request body
- error reading next multipart
- channel participation API is disabled
- form contains too many parts
AI-assisted analysis of hyperledger/fabric@2736b63f8f (2026-09-04).
Data as JSON: /api/errors/21aedb3c458e404b.
Report an issue: GitHub.