hyperledger/fabric · error

cannot unmarshal file part %s into a block

Error message

cannot unmarshal file part %s into a block

What it means

This error wraps a proto.Unmarshal failure: the bytes uploaded as the 'config-block' file part are not a valid protobuf-encoded common.Block. The handler logs the unmarshal failure at debug level and returns HTTP 400 with this message. It means the payload arrived intact but is not the expected block format (wrong file, corrupted, base64/JSON instead of raw protobuf bytes).

Source

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

	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
}

// Expect a multipart/form-data with a single part, of type file, with key FormDataConfigUpdateEnvelopeKey.
func (h *HTTPHandler) multipartFormDataBodyToEnvelope(params map[string]string, req *http.Request, resp http.ResponseWriter) *cb.Envelope {
	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
	}

View on GitHub (pinned to 2736b63f8f)

Solutions

  1. Regenerate the genesis block with configtxgen (configtxgen -profile ... -outputBlock genesis.block) and upload that raw file
  2. Ensure the client sends the raw protobuf block bytes, not base64 or JSON representations — decode first if your tooling encodes it
  3. Verify the file with 'configtxgen -inspectBlock genesis.block' or 'osnadmin channel join' prerequisites before uploading
  4. Confirm you are attaching the correct file (genesis/config block), not a config-update envelope or certificate

Example fix

# before: uploading base64-encoded block
base64 genesis.block | curl -X POST .../join -F 'config-block=@-;type=application/octet-stream'
# after: upload raw block bytes
curl -X POST .../join -F 'config-block=@genesis.block'
Defensive patterns

Strategy: validation

Validate before calling

// validate the block parses before uploading
block := &common.Block{}
if err := proto.Unmarshal(blockBytes, block); err != nil {
    return fmt.Errorf("%s is not a valid protobuf block: %w", blockPath, err)
}
// optionally sanity-check the header
if block.Header == nil || block.Header.Number != 0 {
    return errors.New("expected a genesis block (number 0) with a header")
}

Type guard

func isProtoBlock(b []byte) bool {
    blk := &common.Block{}
    return proto.Unmarshal(b, blk) == nil && blk.Header != nil
}

Try / catch

if resp.StatusCode == http.StatusBadRequest {
    body, _ := io.ReadAll(resp.Body)
    return fmt.Errorf("invalid config-block payload (check it is a raw protobuf block, not base64/JSON): %s", body)
}

Prevention

When it happens

Trigger: POSTing to /participation/v1/channels/{channel}/join with a 'config-block' part whose bytes do not deserialize into a cb.Block — e.g. a JSON/block-string config, a transaction envelope, a PEM cert, or a text error page saved as the block file.

Common situations: Using 'configtxgen -outputBlock' output incorrectly transformed (base64-encoded by a script); downloading the genesis block via an API that returns JSON and re-uploading it raw; accidentally attaching the wrong file (TLS cert, channel tx); truncated block written by a failed fetch.

Related errors


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