hyperledger/fabric · error

cannot open file part %s from request body

Error message

cannot open file part %s from request body

What it means

This error wraps the OS/multipart error returned when the server cannot open the uploaded file part from the request body. After locating the 'config-block' file part, the handler calls fileHeader.Open(); if that fails the error is wrapped and returned with HTTP 400. It indicates a malformed multipart stream or an I/O problem reading the uploaded part, not a problem with the block content itself.

Source

Thrown at orderer/common/channelparticipation/restapi.go:449

	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))
		return nil
	}

	block := &cb.Block{}
	err = proto.Unmarshal(blockBytes, block)
	if err != nil {
		h.logger.Debugf("Failed to unmarshal blockBytes: %s", err)
		h.sendResponseJsonError(resp, http.StatusBadRequest, errors.Wrapf(err, "cannot unmarshal file part %s into a block", FormDataConfigBlockKey))
		return nil
	}

	return block

View on GitHub (pinned to 2736b63f8f)

Solutions

  1. Retry the upload ensuring the client fully writes the multipart body before awaiting the response
  2. Verify the HTTP client generates a valid multipart/form-data body (use a standard library like curl, requests, or Go's mime/multipart)
  3. Check proxy/gateway timeout and body-size settings so the upload is not truncated
  4. Capture the wrapped cause in the response to identify the underlying open error

Example fix

// before: hand-built multipart body with wrong boundary headers
http.Post(url, "multipart/form-data", body)
// after
var b bytes.Buffer
w := multipart.NewWriter(&b)
f, _ := w.CreateFormFile("config-block", "genesis.block")
f.Write(blockBytes)
w.Close()
http.Post(url, w.FormDataContentType(), &b)
Defensive patterns

Strategy: try-catch

Validate before calling

// pre-flight: ensure the block file exists and is readable client-side
st, err := os.Stat(blockPath)
if err != nil || st.Size() == 0 {
    return fmt.Errorf("block file %s missing or empty: %w", blockPath, err)
}

Try / catch

resp, err := client.Post(url, w.FormDataContentType(), &buf)
if err != nil {
    return fmt.Errorf("upload interrupted, retry with full body write: %w", err)
}
if resp.StatusCode == http.StatusBadRequest {
    var e map[string]string
    json.NewDecoder(resp.Body).Decode(&e)
    return fmt.Errorf("server rejected multipart body: %v", e)
}

Prevention

When it happens

Trigger: POSTing to the join endpoint where the multipart file part for 'config-block' exists but its embedded file cannot be opened — typically a truncated or malformed multipart body, or the connection dropping mid-read.

Common situations: Proxy/load-balancer truncating large uploads; client timing out mid-upload and closing the stream; malformed multipart boundary produced by a hand-rolled HTTP client; body exceeding MaxBytesReader limits causing read failures.

Related errors


AI-assisted analysis of hyperledger/fabric@2736b63f8f (2026-09-04). Data as JSON: /api/errors/722e68131af101cc. Report an issue: GitHub.