hyperledger/fabric · error

error marshaling Response: proto: Marshal called with nil

Error message

error marshaling Response: proto: Marshal called with nil

What it means

GetBytesResponse serializes a *peer.Response to bytes via proto.Marshal. This error is returned explicitly when the caller passes a nil Response pointer, because gogo/proto's Marshal panics or fails when called with a nil message. The library guards the nil case and returns a descriptive error instead of crashing.

Source

Thrown at protoutil/proputils.go:146

		ProposalHash: hash,
	}
	prpBytes, err := proto.Marshal(prp)
	return prpBytes, errors.Wrap(err, "error marshaling ProposalResponsePayload")
}

// GetBytesChaincodeProposalPayload gets the chaincode proposal payload
func GetBytesChaincodeProposalPayload(cpp *peer.ChaincodeProposalPayload) ([]byte, error) {
	if cpp == nil {
		return nil, errors.New("error marshaling ChaincodeProposalPayload: proto: Marshal called with nil")
	}
	cppBytes, err := proto.Marshal(cpp)
	return cppBytes, errors.Wrap(err, "error marshaling ChaincodeProposalPayload")
}

// GetBytesResponse gets the bytes of Response
func GetBytesResponse(res *peer.Response) ([]byte, error) {
	if res == nil {
		return nil, errors.New("error marshaling Response: proto: Marshal called with nil")
	}
	resBytes, err := proto.Marshal(res)
	return resBytes, errors.Wrap(err, "error marshaling Response")
}

// GetBytesChaincodeEvent gets the bytes of ChaincodeEvent
func GetBytesChaincodeEvent(event *peer.ChaincodeEvent) ([]byte, error) {
	if event == nil {
		return nil, errors.New("error marshaling ChaincodeEvent: proto: Marshal called with nil")
	}
	eventBytes, err := proto.Marshal(event)
	return eventBytes, errors.Wrap(err, "error marshaling ChaincodeEvent")
}

// GetBytesChaincodeActionPayload get the bytes of ChaincodeActionPayload from
// the message
func GetBytesChaincodeActionPayload(cap *peer.ChaincodeActionPayload) ([]byte, error) {
	if cap == nil {

View on GitHub (pinned to 2736b63f8f)

Solutions

  1. Check the *peer.Response for nil before calling GetBytesResponse.
  2. If extracting from a ProposalResponse, verify that pResp.Response was populated (e.g. the proposal actually succeeded).
  3. Return or propagate a descriptive error upstream instead of marshaling.
  4. In tests, initialize a valid &peer.Response{} rather than a nil pointer.

Example fix

// before
resBytes, err := protoutil.GetBytesResponse(pResp.Response)
// after
if pResp == nil || pResp.Response == nil {
    return nil, errors.New("proposal response missing Response payload")
}
resBytes, err := protoutil.GetBytesResponse(pResp.Response)
Defensive patterns

Strategy: validation

Validate before calling

if res == nil {
    return nil, errors.New("cannot serialize: peer.Response is nil")
}

Type guard

func hasResponse(pResp *peer.ProposalResponse) bool {
    return pResp != nil && pResp.Response != nil
}

Try / catch

resBytes, err := protoutil.GetBytesResponse(res)
if err != nil {
    return fmt.Errorf("GetBytesResponse: %w", err)
}

Prevention

When it happens

Trigger: Calling protoutil.GetBytesResponse(nil), or passing a struct field like pResp.Response that was never assigned because the ProposalResponse failed to populate.

Common situations: Processing a peer proposal response where the chaincode returned no action, deserializing payloads from malformed or truncated transactions, or test harnesses (TestProposalResponse) exercising nil inputs.

Related errors


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