hyperledger/fabric · error
failed to unmarshal response for transaction %s
Error message
failed to unmarshal response for transaction %s
What it means
This error is wrapped by processChaincodeExecutionResult when a chaincode message of type COMPLETED arrives, but its payload cannot be proto-unmarshaled into a pb.Response. It means the peer received a 'successful' completion message from the chaincode whose bytes are not a valid serialized Response (status, message, payload fields). The underlying proto error is wrapped so the txid is included. This usually indicates a corrupt or malformed payload produced by the chaincode side or an incompatible protobuf schema.
Source
Thrown at core/chaincode/chaincode_support.go:191
func processChaincodeExecutionResult(txid, ccName string, resp *pb.ChaincodeMessage, err error) (*pb.Response, *pb.ChaincodeEvent, error) {
if err != nil {
return nil, nil, errors.Wrapf(err, "failed to execute transaction %s", txid)
}
if resp == nil {
return nil, nil, errors.Errorf("nil response from transaction %s", txid)
}
if resp.ChaincodeEvent != nil {
resp.ChaincodeEvent.ChaincodeId = ccName
resp.ChaincodeEvent.TxId = txid
}
switch resp.Type {
case pb.ChaincodeMessage_COMPLETED:
res := &pb.Response{}
err := proto.Unmarshal(resp.Payload, res)
if err != nil {
return nil, nil, errors.Wrapf(err, "failed to unmarshal response for transaction %s", txid)
}
return res, resp.ChaincodeEvent, nil
case pb.ChaincodeMessage_ERROR:
return nil, resp.ChaincodeEvent, errors.Errorf("transaction returned with failure: %s", resp.Payload)
default:
return nil, nil, errors.Errorf("unexpected response type %d for transaction %s", resp.Type, txid)
}
}
// Invoke will invoke chaincode and return the message containing the response.
// The chaincode will be launched if it is not already running.
func (cs *ChaincodeSupport) Invoke(txParams *ccprovider.TransactionParams, chaincodeName string, input *pb.ChaincodeInput) (*pb.ChaincodeMessage, error) {
ccid, cctype, err := cs.CheckInvocation(txParams, chaincodeName, input)
if err != nil {
return nil, errors.WithMessage(err, "invalid invocation")
}View on GitHub (pinned to 2736b63f8f)
Solutions
- Inspect the chaincode: ensure it returns responses through the shim (shim.Success/shim.Error) so the payload is a valid marshaled pb.Response.
- Align peer and chaincode fabric versions / protobuf definitions so the Response schema matches.
- Reproduce locally with the same input and log the raw resp.Payload bytes to identify the malformed sender.
- Update or fix any custom middleware/decoration that rewrites chaincode messages in flight.
- Retry the transaction; if corruption is transient (stream glitch), re-execution typically succeeds.
Example fix
// before: chaincode returning a hand-built COMPLETED message
msg := &pb.ChaincodeMessage{Type: pb.ChaincodeMessage_COMPLETED, Payload: []byte("OK"), Txid: txid}
// after: return a proper marshaled pb.Response via the shim
res := &pb.Response{Status: 200, Payload: result}
payload, _ := proto.Marshal(res)
msg := &pb.ChaincodeMessage{Type: pb.ChaincodeMessage_COMPLETED, Payload: payload, Txid: txid} Defensive patterns
Strategy: try-catch
Validate before calling
// client-side: keep peer and chaincode protos in sync; verify the response decodes
var res pb.Response
if err := proto.Unmarshal(completedMsg.Payload, &res); err != nil {
return fmt.Errorf("malformed chaincode response payload for tx %s: %w", txid, err)
} Type guard
func isCompletedWithValidResponse(msg *pb.ChaincodeMessage) (*pb.Response, bool) {
if msg == nil || msg.Type != pb.ChaincodeMessage_COMPLETED {
return nil, false
}
res := &pb.Response{}
if proto.Unmarshal(msg.Payload, res) != nil {
return nil, false
}
return res, true
} Try / catch
res, ccEvent, err := chaincodeSupport.Execute(txParams, ccName, input)
if err != nil {
if strings.Contains(err.Error(), "failed to unmarshal response") {
// malformed payload: inspect chaincode shim version/protos, then retry once
return retryTransaction(txParams)
}
return err
} Prevention
- Always return results through shim.Success/shim.Error, never hand-build COMPLETED messages.
- Pin identical Fabric versions for peer and chaincode images; rebuild chaincode on upgrades.
- Run integration tests that assert response payloads unmarshal after any proto change.
- Log raw payloads when DEBUG-level chaincode logging is enabled to catch corruption early.
When it happens
Trigger: A chaincode sends a ChaincodeMessage_COMPLETED whose Payload bytes are empty, truncated, or not a marshaled pb.Response (e.g. chaincode code constructs the COMPLETED message manually instead of via GetReturnValue/response helpers, or a corrupted frame crossed the gRPC stream). Triggered via ChaincodeSupport.Execute or ExecuteLegacyInit -> processChaincodeExecutionResult.
Common situations: Custom chaincode shim modifications or forks that emit raw COMPLETED payloads; protobuf schema mismatches between peer and chaincode (mixed fabric versions); corrupted messages after network issues; third-party SDKs building the message by hand.
Understand the failure class
Background: "cannot parse invalid wire-format data", "cannot unmarshal", "failed unmarshalling": protobuf unmarshal errors explained — this error's family across 10 libraries.
Related errors
- could not unmarshal chaincode package to CDS or SignedCDS
- failed to unmarshal deployment spec from bytes
- failed to deserialize values
- error converting envelope to config update: %s
- unmarshal failed
AI-assisted analysis of hyperledger/fabric@2736b63f8f (2026-09-04).
Data as JSON: /api/errors/261008fa3ae4fe25.
Report an issue: GitHub.