hyperledger/fabric · error

cannot open file part

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.

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.

Appendix: 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)