hyperledger/fabric · error

response is of type %v, but expected a block

Error message

response is of type %v, but expected a block

What it means

extractBlockFromResponse hits its default case when the DeliverResponse payload Type is not a DeliverResponse_BLOCK — the remote ordering node answered with a status (or nothing block-shaped) instead of the requested block. This means the deliver stream did not deliver what the BlockPuller asked for.

Source

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

			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
		}
		return nil, errors.Errorf("faulty node, received: %v", resp)
	default:
		return nil, errors.Errorf("response is of type %v, but expected a block", reflect.TypeOf(resp.Type))
	}
}

func (p *BlockPuller) seekLastEnvelope() (*common.Envelope, error) {
	return protoutil.CreateSignedEnvelopeWithTLSBinding(
		common.HeaderType_DELIVER_SEEK_INFO,
		p.Channel,
		p.Signer,
		last(),
		int32(0),
		uint64(0),
		util.ComputeSHA256(p.TLSCert),
	)
}

func (p *BlockPuller) seekNextEnvelope(startSeq uint64) (*common.Envelope, error) {
	return protoutil.CreateSignedEnvelopeWithTLSBinding(
		common.HeaderType_DELIVER_SEEK_INFO,

View on GitHub (pinned to 2736b63f8f)

Solutions

  1. Check the status embedded in the response in the orderer logs to see why a block was not returned
  2. Re-pull from a different cluster endpoint — the puller retries other endpoints automatically
  3. Align Fabric versions across all ordering nodes
  4. Verify the endpoint list in the cluster configuration points at actual consenter nodes of the channel
Defensive patterns

Strategy: type-guard

Validate before calling

if resp.GetType() != orderer.DeliverResponse_BLOCK { log.Printf("got status %v instead of block", resp.GetStatus()) }

Type guard

func extractStatus(resp *orderer.DeliverResponse) (common.Status, bool) {
    if resp == nil || resp.GetType() != orderer.DeliverResponse_Status { return 0, false }
    return resp.GetStatus(), true
}

Try / catch

blockResp, err := p.extractBlockFromResponse(resp)
if err != nil {
    var status common.Status
    if resp.GetType() == orderer.DeliverResponse_Status { status = resp.GetStatus() }
    // branch on status or retry another endpoint
    return err
}

Prevention

When it happens

Trigger: The remote node returns a DeliverResponse whose Type is DeliverResponse_Status (e.g. NOT_FOUND, BAD_REQUEST, FORBIDDEN not matching the special-cased statuses) instead of a block; a malformed or foreign message on the deliver stream.

Common situations: Requesting a block (e.g. latest config block for eviction detection) from a node that no longer services the channel; fabric binary skew between nodes; corrupted or spoofed responses from a wrong endpoint.

Related errors


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