{"record":{"id":"e10a85d50be61807","repo":"hyperledger/fabric","slug":"empty-nonce","errorCode":null,"errorMessage":"empty nonce","messagePattern":"empty nonce","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"core/tx/endorser/parser.go","lineNumber":141,"sourceCode":"\t\tNonce:        txenv.SignatureHeader.Nonce,\n\t}, nil\n}\n\nfunc (e *EndorserTx) validate() error {\n\tif e.Epoch != 0 {\n\t\treturn errors.Errorf(\"invalid epoch in ChannelHeader. Expected 0, got [%d]\", e.Epoch)\n\t}\n\n\tif e.Version != 0 {\n\t\treturn errors.Errorf(\"invalid version in ChannelHeader. Expected 0, got [%d]\", e.Version)\n\t}\n\n\tif err := ValidateChannelID(e.ChannelID); err != nil {\n\t\treturn err\n\t}\n\n\tif len(e.Nonce) == 0 {\n\t\treturn errors.New(\"empty nonce\")\n\t}\n\n\tif len(e.Creator) == 0 {\n\t\treturn errors.New(\"empty creator\")\n\t}\n\n\tif e.ChaincodeID == nil {\n\t\treturn errors.New(\"nil ChaincodeId\")\n\t}\n\n\tif e.ChaincodeID.Name == \"\" {\n\t\treturn errors.New(\"empty chaincode name in chaincode id\")\n\t}\n\n\t// TODO FAB-16170: check proposal hash\n\n\t// TODO FAB-16170: verify that txid matches the one in the header\n","sourceCodeStart":123,"sourceCodeEnd":159,"githubUrl":"https://github.com/hyperledger/fabric/blob/2736b63f8fd5932511d56fe68b7039d15977f7f6/core/tx/endorser/parser.go#L123-L159","documentation":"The SignatureHeader's Nonce is empty. Fabric requires every endorser transaction to carry a fresh random nonce that, together with the creator identity and txid, prevents replay. An empty nonce means the signature header was not populated properly and the transaction would be invalid on the network.","triggerScenarios":"UnmarshalEndorserTxAndValidate is given an envelope whose SignatureHeader.Nonce is a zero-length byte slice — the header was built without generating/util.GetRandomNonce, or the nonce was dropped during assembly.","commonSituations":"Custom transaction assembly forgetting util.GetRandomNonce(); caching/reusing header structs and overwriting nonce with nil; SDK misconfiguration in the transaction-generation pipeline.","solutions":["Generate a fresh nonce with util.GetRandomNonce() and set SignatureHeader.Nonce when building the transaction.","Ensure each transaction uses a NEW nonce — never reuse or blank it for retried submits.","Verify the code path that serializes the SignatureHeader preserves the nonce bytes."],"exampleFix":"// before\nsh := &common.SignatureHeader{Creator: creator} // nonce missing\n// after\nsh := &common.SignatureHeader{Creator: creator, Nonce: util.GetRandomNonce()}","handlingStrategy":"validation","validationCode":"func hasNonce(sh *common.SignatureHeader) bool {\n    return len(sh.GetNonce()) > 0\n}\n// before submit: if !hasNonce(sigHeader) { sigHeader.Nonce = util.GetRandomNonce() }","typeGuard":"func noncePresent(sh *common.SignatureHeader) bool {\n    return sh != nil && len(sh.Nonce) > 0\n}","tryCatchPattern":"tx, err := parser.UnmarshalEndorserTxAndValidate(env)\nif err != nil {\n    if strings.Contains(err.Error(), \"empty nonce\") {\n        // signature header built without nonce: regenerate tx with a fresh nonce\n        return ErrInvalidHeader\n    }\n    return err\n}","preventionTips":["Always set SignatureHeader.Nonce via util.GetRandomNonce().","Never reuse a nonce across transactions; generate a fresh one per submit.","Verify the header survives serialization without dropping the nonce field."],"tags":["hyperledger-fabric","signature-header","validation"],"backgroundTag":"missing-nonce","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"}