{"record":{"id":"01eb00048e5bf036","repo":"hyperledger/fabric","slug":"only-one-action-per-transaction-is-supported-tx-c","errorCode":null,"errorMessage":"only one action per transaction is supported, tx contains %d","messagePattern":"only one action per transaction is supported, tx contains (.+?)","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"core/common/validation/msgvalidation.go","lineNumber":190,"sourceCode":"\n\t// if the type is ENDORSER_TRANSACTION we unmarshal a Transaction message\n\ttx, err := protoutil.UnmarshalTransaction(data)\n\tif err != nil {\n\t\treturn err\n\t}\n\n\t// check for nil argument\n\tif tx == nil {\n\t\treturn errors.New(\"nil transaction\")\n\t}\n\n\t// TODO: validate tx.Version\n\n\t// TODO: validate ChaincodeHeaderExtension\n\n\t// hlf version 1 only supports a single action per transaction\n\tif len(tx.Actions) != 1 {\n\t\treturn errors.Errorf(\"only one action per transaction is supported, tx contains %d\", len(tx.Actions))\n\t}\n\n\tputilsLogger.Debugf(\"validateEndorserTransaction info: there are %d actions\", len(tx.Actions))\n\n\tfor _, act := range tx.Actions {\n\t\t// check for nil argument\n\t\tif act == nil {\n\t\t\treturn errors.New(\"nil action\")\n\t\t}\n\n\t\t// if the type is ENDORSER_TRANSACTION we unmarshal a SignatureHeader\n\t\tsHdr, err := protoutil.UnmarshalSignatureHeader(act.Header)\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\n\t\t// validate the SignatureHeader - here we actually only\n\t\t// care about the nonce since the creator is in the outer header","sourceCodeStart":172,"sourceCodeEnd":208,"githubUrl":"https://github.com/hyperledger/fabric/blob/2736b63f8fd5932511d56fe68b7039d15977f7f6/core/common/validation/msgvalidation.go#L172-L208","documentation":"Hyperledger Fabric v1.x supports exactly one action per endorser transaction. validateEndorserTransaction returns this error when the unmarshalled Transaction contains more or fewer than one TransactionAction, using errors.Errorf with the actual action count.","triggerScenarios":"ValidateTransaction receiving a common.Transaction whose Actions slice length != 1 (0 actions, or 2+ actions concatenated from multiple proposals).","commonSituations":"Client SDKs (or custom code) merging multiple proposal responses into a single transaction; protobuf unions with Actions == nil (empty message); upgrades from formats that allowed multiple actions.","solutions":["Build the transaction from exactly one set of collected proposal endorsements (one TransactionAction)","If multiple proposal responses were concatenated, submit them as separate transactions","Verify the SDK call (e.g. createTransaction with a single proposal response) rather than an array"],"exampleFix":"// before\ntx.Actions = []*common.TransactionAction{action1, action2}\n// after\ntx.Actions = []*common.TransactionAction{action1} // one action per tx in v1.x","handlingStrategy":"validation","validationCode":"if len(tx.Actions) != 1 { return fmt.Errorf(\"expected 1 action, got %d\", len(tx.Actions)) }","typeGuard":"func isSingleActionTx(tx *common.Transaction) bool {\n\treturn tx != nil && len(tx.Actions) == 1\n}","tryCatchPattern":null,"preventionTips":["Create transactions from a single proposal response set","Never concatenate multiple proposal responses into one transaction","On Fabric v1.x, assume exactly one action per endorser transaction"],"tags":["fabric","transaction-validation","endorser-transaction"],"backgroundTag":"transaction-shape-validation","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"}