hyperledger/fabric · error

block is nil

Error message

block is nil

What it means

extractBlockFromResponse unwraps a DeliverResponse of type Block. If the Block message inside the response is nil, there is no block to process, and the helper rejects it with this error rather than panicking downstream.

Source

Thrown at orderer/common/cluster/deliver.go:459

	if err != nil {
		p.Logger.Warningf("Failed establishing deliver stream with %s", endpoint)
		return nil, err
	}

	if err = stream.Send(env); err != nil {
		p.Logger.Errorf("Failed sending seek envelope to %s: %v", endpoint, err)
		stream.abort()
		return nil, err
	}
	return stream, nil
}

func extractBlockFromResponse(resp *orderer.DeliverResponse) (*common.Block, error) {
	switch t := resp.Type.(type) {
	case *orderer.DeliverResponse_Block:
		block := t.Block
		if block == nil {
			return nil, errors.New("block is nil")
		}
		if block.Data == nil {
			return nil, errors.New("block data is nil")
		}
		if block.Header == nil {
			return nil, errors.New("block header is nil")
		}
		if block.Metadata == nil || len(block.Metadata.Metadata) == 0 {
			return nil, errors.New("block metadata is empty")
		}
		return block, nil
	case *orderer.DeliverResponse_Status:
		if t.Status == common.Status_FORBIDDEN {
			return nil, ErrForbidden
		}
		if t.Status == common.Status_SERVICE_UNAVAILABLE {
			return nil, ErrServiceUnavailable
		}

View on GitHub (pinned to 2736b63f8f)

Solutions

  1. Retry the block fetch (the puller advances to the next response/reconnects)
  2. Inspect the remote orderer logs for why it emitted an empty block response
  3. Verify no proxy/intermediary is corrupting the deliver stream between nodes
Defensive patterns

Strategy: validation

Validate before calling

if resp.GetType() == &orderer.DeliverResponse_Block{} && resp.GetBlock() == nil {
    return fmt.Errorf("received empty block response")
}

Type guard

func isUsableBlock(resp *orderer.DeliverResponse) bool {
    b := resp.GetBlock()
    return b != nil && b.Data != nil && b.Header != nil && b.Metadata != nil && len(b.Metadata.Metadata) > 0
}

Try / catch

block, err := extractBlockFromResponse(resp)
if err != nil {
    log.Errorf("bad block from %s: %v", endpoint, err)
    return err // puller will retry/advance
}

Prevention

When it happens

Trigger: pullBlocks or fetchLastBlockSeq received a DeliverResponse_Block whose Block field is nil — a malformed or empty block response from the remote deliver service.

Common situations: Malfunctioning or buggy remote orderer sending empty block envelopes; truncated/corrupt gRPC message; middleware/proxy stripping payload fields.

Related errors


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