hyperledger/fabric · error

Block data is empty

Error message

Block data is empty

What it means

coordinator.StoreBlock validates the incoming common.Block before committing it to the ledger and returns this error when block.Data is nil. A block without data payload cannot be validated or committed, so it is rejected immediately.

Source

Thrown at gossip/privdata/coordinator.go:155

) Coordinator {
	return &coordinator{
		Support:                        support,
		mspID:                          mspID,
		store:                          store,
		selfSignedData:                 selfSignedData,
		transientBlockRetention:        config.TransientBlockRetention,
		logger:                         logger.With("channel", support.ChainID),
		metrics:                        metrics,
		pullRetryThreshold:             config.PullRetryThreshold,
		skipPullingInvalidTransactions: config.SkipPullingInvalidTransactions,
		idDeserializerFactory:          idDeserializerFactory,
	}
}

// StoreBlock stores block with private data into the ledger
func (c *coordinator) StoreBlock(block *common.Block, privateDataSets util.PvtDataCollections) error {
	if block.Data == nil {
		return errors.New("Block data is empty")
	}
	if block.Header == nil {
		return errors.New("Block header is nil")
	}

	c.logger.Infof("Received block [%d] from buffer", block.Header.Number)

	c.logger.Debugf("Validating block [%d]", block.Header.Number)

	validationStart := time.Now()
	err := c.Validator.Validate(block)
	c.reportValidationDuration(time.Since(validationStart))
	if err != nil {
		c.logger.Errorf("Validation failed: %+v", err)
		return err
	}

	blockAndPvtData := &ledger.BlockAndPvtData{

View on GitHub (pinned to 2736b63f8f)

Solutions

  1. Re-fetch the block from the orderer or a peer via block delivery/delclient
  2. Discard or re-request the corrupted block from gossip source
  3. Verify block deserialization (protoutil) succeeded before calling StoreBlock
  4. In test/repair code, always populate block.Data before storing

Example fix

// before
coordinator.StoreBlock(&common.Block{}, nil)
// after
blk := &common.Block{Header: header, Data: &common.BlockData{Data: [][]byte{...}}}
if blk.Data == nil || blk.Header == nil {
    return errors.New("refusing to store incomplete block")
}
coordinator.StoreBlock(blk, pvtData)
Defensive patterns

Strategy: validation

Validate before calling

if block == nil || block.Data == nil {
    return errors.New("cannot store block: data is nil")
}
if err := coordinator.StoreBlock(block, pvtData); err != nil { ... }

Type guard

func blockComplete(b *common.Block) bool {
    return b != nil && b.Data != nil && b.Header != nil
}

Prevention

When it happens

Trigger: Calling StoreBlock with a block whose Data field is nil — e.g. a malformed block fetched from gossip/orderer, a partially deserialized block, or a hand-constructed block in tests.

Common situations: Corrupted gossip transfer of blocks; orderer returning truncated blocks; off-chain ledger repair tooling feeding empty blocks; unit tests constructing common.Block without Data.

Related errors


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