hyperledger/fabric · error
marshal failed
Error message
marshal failed
What it means
After fetching the values, the handler serializes pb.GetStateMultipleResult back to the chaincode with proto.Marshal. If Marshal fails (extremely rare; e.g. internal protobuf state corruption), the error is wrapped with 'marshal failed' and returned to the shim as an ERROR message. This is a server-side serialization failure, not caused by user input format.
Source
Thrown at core/chaincode/handler.go:746
return nil, errors.New("private data APIs are not allowed in chaincode Init()")
}
if err = errorIfCreatorHasNoReadPermission(namespaceID, collection, txContext); err != nil {
return nil, err
}
res, err = txContext.TXSimulator.GetPrivateDataMultipleKeys(namespaceID, collection, getState.GetKeys())
} else {
res, err = txContext.TXSimulator.GetStateMultipleKeys(namespaceID, getState.GetKeys())
}
if err != nil {
return nil, errors.WithStack(err)
}
if len(res) == 0 {
chaincodeLogger.Debugf("[%s] No state associated with keys: %v. Sending %s with an empty payload", shorttxid(msg.Txid), getState.GetKeys(), pb.ChaincodeMessage_RESPONSE)
}
payloadBytes, err := proto.Marshal(&pb.GetStateMultipleResult{Values: res})
if err != nil {
return nil, errors.Wrap(err, "marshal failed")
}
// Send response msg back to chaincode. GetState will not trigger event
return &pb.ChaincodeMessage{Type: pb.ChaincodeMessage_RESPONSE, Payload: payloadBytes, Txid: msg.Txid, ChannelId: msg.ChannelId}, nil
}
func (h *Handler) HandleGetPrivateDataHash(msg *pb.ChaincodeMessage, txContext *TransactionContext) (*pb.ChaincodeMessage, error) {
getState := &pb.GetState{}
err := proto.Unmarshal(msg.Payload, getState)
if err != nil {
return nil, errors.Wrap(err, "unmarshal failed")
}
var res []byte
namespaceID := txContext.NamespaceID
collection := getState.Collection
chaincodeLogger.Debugf("[%s] getting private data hash for chaincode %s, key %s, channel %s", shorttxid(msg.Txid), namespaceID, getState.Key, txContext.ChannelID)
if txContext.IsInitTransaction {View on GitHub (pinned to 2736b63f8f)
Solutions
- Rebuild the peer with consistent, pinned protobuf/gogo-protobuf versions.
- Check the fetched values res for nil sub-messages or invalid byte slices that confuse the marshaller.
- Upgrade Hyperledger Fabric to a version with matching generated pb code.
- Inspect peer logs for the underlying wrapped error for the exact cause.
Defensive patterns
Strategy: retry
Type guard
func marshalableResult(values [][]byte) bool { _, err := proto.Marshal(&pb.GetStateMultipleResult{Values: values}); return err == nil } Try / catch
payload, err := stub.GetStateByMultipleKeys(collection, keys)
if err != nil && strings.Contains(err.Error(), "marshal failed") {
// retry once; if persistent, escalate to peer upgrade
return retryGetState(keys)
} Prevention
- Keep peer binaries and vendored protobuf runtimes consistent and up to date.
- Avoid exotic/nil sub-values in state bytes.
- Escalate persistent occurrences as a peer bug with logs attached.
When it happens
Trigger: proto.Marshal(&pb.GetStateMultipleResult{Values: res}) fails — practically only when protobuf internal marshaling errors (e.g. nested message set to an invalid state) or resource/size issues occur.
Common situations: Very rare in practice; seen with corrupted protobuf runtime, exotic value bytes, or version-skewed generated code between the peer's protos and its protoc-gen-go runtime.
Related errors
AI-assisted analysis of hyperledger/fabric@2736b63f8f (2026-09-04).
Data as JSON: /api/errors/8e1a04ffbbc14e82.
Report an issue: GitHub.