{"record":{"id":"836359c9e90682c2","repo":"hyperledger/fabric","slug":"only-one-transaction-action-is-supported-d-were","errorCode":null,"errorMessage":"only one transaction action is supported, %d were present","messagePattern":"only one transaction action is supported, (.+?) were present","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"core/tx/endorser/parser.go","lineNumber":64,"sourceCode":"\n\thdrExt, err := protoutil.UnmarshalChaincodeHeaderExtension(\n\t\ttxenv.ChannelHeader.Extension,\n\t)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\tif len(txenv.Data) == 0 {\n\t\treturn nil, errors.New(\"nil payload data\")\n\t}\n\n\ttx, err := protoutil.UnmarshalTransaction(txenv.Data)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\tif len(tx.GetActions()) != 1 {\n\t\treturn nil, errors.Errorf(\"only one transaction action is supported, %d were present\", len(tx.GetActions()))\n\t}\n\n\ttxAction := tx.GetActions()[0]\n\n\tif txAction == nil {\n\t\treturn nil, errors.New(\"nil action\")\n\t}\n\n\tif len(txAction.Payload) == 0 {\n\t\treturn nil, errors.New(\"empty ChaincodeActionPayload\")\n\t}\n\n\tccActionPayload, err := protoutil.UnmarshalChaincodeActionPayload(txAction.Payload)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\n\tif ccActionPayload.Action == nil {","sourceCodeStart":46,"sourceCodeEnd":82,"githubUrl":"https://github.com/hyperledger/fabric/blob/2736b63f8fd5932511d56fe68b7039d15977f7f6/core/tx/endorser/parser.go#L46-L82","documentation":"The transaction inside the envelope contains multiple (or zero) TransactionActions. Fabric's endorser transaction format parsed by this library supports exactly one chaincode action per transaction, so any other count is rejected. This is a deliberate structural constraint of this parser, not a generic protobuf failure.","triggerScenarios":"UnmarshalEndorserTxAndValidate receives an envelope whose Transaction.Actions slice has length != 1 — typically a multi-action transaction produced by custom tooling, or a Transaction with no actions at all.","commonSituations":"Older/custom Fabric SDKs or chaincode tooling that batched multiple actions into one transaction; programmatically assembled transactions with duplicate actions; corrupted protobuf that deserialized with zero actions.","solutions":["Split multi-action transactions into one transaction per action before submitting/parsing.","Regenerate the transaction with the standard Fabric SDK/protoutil path, which produces exactly one action.","If parsing, filter client-side: only feed envelopes whose Transaction.Actions length is 1 to this API."],"exampleFix":"// before\ntx.Actions = []*common.TransactionAction{action1, action2}\n// after\ntx.Actions = []*common.TransactionAction{action1} // one action per tx; submit action2 separately","handlingStrategy":"validation","validationCode":"func hasSingleAction(txBytes []byte) bool {\n    tx := &common.Transaction{}\n    if proto.Unmarshal(txBytes, tx) != nil {\n        return false\n    }\n    return len(tx.GetActions()) == 1\n}","typeGuard":"func isSingleActionTx(tx *common.Transaction) bool {\n    return tx != nil && len(tx.GetActions()) == 1 && tx.GetActions()[0] != nil\n}","tryCatchPattern":"tx, err := parser.UnmarshalEndorserTxAndValidate(env)\nif err != nil {\n    var af *feeders.Errors\n    if strings.Contains(err.Error(), \"only one transaction action is supported\") {\n        // split or reject the multi-action transaction\n        return fmt.Errorf(\"unsupported tx: %w\", err)\n    }\n    return err\n}","preventionTips":["Enforce one-action-per-transaction in any custom transaction builder.","Submit each chaincode invocation as its own transaction.","Pre-validate Transaction.Actions length client-side before envelope assembly."],"tags":["hyperledger-fabric","transaction","validation"],"backgroundTag":"transaction-action-count-invalid","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"}