hyperledger/fabric · error
marshal failed: proto: Marshal called with nil
Error message
marshal failed: proto: Marshal called with nil
What it means
In the query-response path, after collecting the query result, the handler sanity-checks that the payload to return is non-nil before proto.Marshal. If getQueryResponseForIterator yields a nil payload, the peer returns an error literally 'marshal failed: proto: Marshal called with nil' and cleans up the query context. It guards against marshalling a nil protobuf message which would otherwise panic or produce a broken response.
Source
Thrown at core/chaincode/handler.go:877
}
rangeIter, err = txContext.TXSimulator.GetStateRangeScanIteratorWithPagination(namespaceID,
startKey, getStateByRange.EndKey, metadata.PageSize)
} else {
rangeIter, err = txContext.TXSimulator.GetStateRangeScanIterator(namespaceID, getStateByRange.StartKey, getStateByRange.EndKey)
}
if err != nil {
return nil, errors.WithStack(err)
}
txContext.InitializeQueryContext(iterID, rangeIter)
payload, err := h.QueryResponseBuilder.BuildQueryResponse(txContext, rangeIter, iterID, isPaginated, totalReturnLimit)
if err != nil {
txContext.CleanupQueryContext(iterID)
return nil, errors.WithStack(err)
}
if payload == nil {
txContext.CleanupQueryContext(iterID)
return nil, errors.New("marshal failed: proto: Marshal called with nil")
}
payloadBytes, err := proto.Marshal(payload)
if err != nil {
txContext.CleanupQueryContext(iterID)
return nil, errors.Wrap(err, "marshal failed")
}
chaincodeLogger.Debugf("Got keys and values. Sending %s", pb.ChaincodeMessage_RESPONSE)
return &pb.ChaincodeMessage{Type: pb.ChaincodeMessage_RESPONSE, Payload: payloadBytes, Txid: msg.Txid, ChannelId: msg.ChannelId}, nil
}
// Handles query to ledger for query state next
func (h *Handler) HandleQueryStateNext(msg *pb.ChaincodeMessage, txContext *TransactionContext) (*pb.ChaincodeMessage, error) {
queryStateNext := &pb.QueryStateNext{}
err := proto.Unmarshal(msg.Payload, queryStateNext)
if err != nil {
return nil, errors.Wrap(err, "unmarshal failed")View on GitHub (pinned to 2736b63f8f)
Solutions
- Upgrade Hyperledger Fabric to the latest patch release; this guard indicates an unexpected nil that upstream fixes have addressed.
- Retry the range/query transaction; transient query-context issues may resolve.
- Check for query-context expiry (totalQueryLimit / query timeout) and reduce result window size or use pagination.
- Inspect peer logs around the query for the underlying ledger error that produced a nil payload.
Defensive patterns
Strategy: retry
Type guard
func hasValidQueryPayload(payload interface{ Reset(); String() string; ProtoMessage() }) bool { return payload != nil && !reflect.ValueOf(payload).IsNil() } Try / catch
iter, err := stub.GetStateByRange(start, end)
if err != nil && strings.Contains(err.Error(), "marshal failed") {
// retry transaction once; if persistent, reduce query window / upgrade peer
return retryRangeQuery(start, end)
} Prevention
- Keep peers on current Fabric patch releases.
- Use pagination and bounded ranges to avoid long-lived query contexts.
- Retry transient query failures; escalate persistent nil-payload errors to the Fabric project.
When it happens
Trigger: The internal query-response builder returns a nil protobuf payload for an iterator ID — e.g. the next-state result construction failed to produce a valid QueryResponse message while iterating range/query results.
Common situations: Peer-side iterator/query-context issues (expired or corrupted query context), ledger provider returning empty result structures, or Fabric bugs in specific versions around paginated queries.
Related errors
- failed to marshal args
- error marshaling: proto: Marshal called with nil
- error marshaling
- malformed org definition for org: %s
- error encode input
AI-assisted analysis of hyperledger/fabric@2736b63f8f (2026-09-04).
Data as JSON: /api/errors/9132fa108b16163a.
Report an issue: GitHub.