{"record":{"id":"261008fa3ae4fe25","repo":"hyperledger/fabric","slug":"failed-to-unmarshal-response-for-transaction-s","errorCode":null,"errorMessage":"failed to unmarshal response for transaction %s","messagePattern":"failed to unmarshal response for transaction (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"core/chaincode/chaincode_support.go","lineNumber":191,"sourceCode":"func processChaincodeExecutionResult(txid, ccName string, resp *pb.ChaincodeMessage, err error) (*pb.Response, *pb.ChaincodeEvent, error) {\n\tif err != nil {\n\t\treturn nil, nil, errors.Wrapf(err, \"failed to execute transaction %s\", txid)\n\t}\n\tif resp == nil {\n\t\treturn nil, nil, errors.Errorf(\"nil response from transaction %s\", txid)\n\t}\n\n\tif resp.ChaincodeEvent != nil {\n\t\tresp.ChaincodeEvent.ChaincodeId = ccName\n\t\tresp.ChaincodeEvent.TxId = txid\n\t}\n\n\tswitch resp.Type {\n\tcase pb.ChaincodeMessage_COMPLETED:\n\t\tres := &pb.Response{}\n\t\terr := proto.Unmarshal(resp.Payload, res)\n\t\tif err != nil {\n\t\t\treturn nil, nil, errors.Wrapf(err, \"failed to unmarshal response for transaction %s\", txid)\n\t\t}\n\t\treturn res, resp.ChaincodeEvent, nil\n\n\tcase pb.ChaincodeMessage_ERROR:\n\t\treturn nil, resp.ChaincodeEvent, errors.Errorf(\"transaction returned with failure: %s\", resp.Payload)\n\n\tdefault:\n\t\treturn nil, nil, errors.Errorf(\"unexpected response type %d for transaction %s\", resp.Type, txid)\n\t}\n}\n\n// Invoke will invoke chaincode and return the message containing the response.\n// The chaincode will be launched if it is not already running.\nfunc (cs *ChaincodeSupport) Invoke(txParams *ccprovider.TransactionParams, chaincodeName string, input *pb.ChaincodeInput) (*pb.ChaincodeMessage, error) {\n\tccid, cctype, err := cs.CheckInvocation(txParams, chaincodeName, input)\n\tif err != nil {\n\t\treturn nil, errors.WithMessage(err, \"invalid invocation\")\n\t}","sourceCodeStart":173,"sourceCodeEnd":209,"githubUrl":"https://github.com/hyperledger/fabric/blob/2736b63f8fd5932511d56fe68b7039d15977f7f6/core/chaincode/chaincode_support.go#L173-L209","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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."],"exampleFix":"// before: chaincode returning a hand-built COMPLETED message\nmsg := &pb.ChaincodeMessage{Type: pb.ChaincodeMessage_COMPLETED, Payload: []byte(\"OK\"), Txid: txid}\n// after: return a proper marshaled pb.Response via the shim\nres := &pb.Response{Status: 200, Payload: result}\npayload, _ := proto.Marshal(res)\nmsg := &pb.ChaincodeMessage{Type: pb.ChaincodeMessage_COMPLETED, Payload: payload, Txid: txid}","handlingStrategy":"try-catch","validationCode":"// client-side: keep peer and chaincode protos in sync; verify the response decodes\nvar res pb.Response\nif err := proto.Unmarshal(completedMsg.Payload, &res); err != nil {\n    return fmt.Errorf(\"malformed chaincode response payload for tx %s: %w\", txid, err)\n}","typeGuard":"func isCompletedWithValidResponse(msg *pb.ChaincodeMessage) (*pb.Response, bool) {\n    if msg == nil || msg.Type != pb.ChaincodeMessage_COMPLETED {\n        return nil, false\n    }\n    res := &pb.Response{}\n    if proto.Unmarshal(msg.Payload, res) != nil {\n        return nil, false\n    }\n    return res, true\n}","tryCatchPattern":"res, ccEvent, err := chaincodeSupport.Execute(txParams, ccName, input)\nif err != nil {\n    if strings.Contains(err.Error(), \"failed to unmarshal response\") {\n        // malformed payload: inspect chaincode shim version/protos, then retry once\n        return retryTransaction(txParams)\n    }\n    return err\n}","preventionTips":["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."],"tags":["protobuf","unmarshal","chaincode","hyperledger-fabric"],"backgroundTag":"protobuf-unmarshal-failed","analyzedSha":"2736b63f8fd5932511d56fe68b7039d15977f7f6","analyzedAt":"2026-09-04T08:52:36.465Z","contentChangedAt":"2026-09-04T08:52:36.465Z","schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}