{"record":{"id":"2a17600698da915f","repo":"hyperledger/fabric","slug":"incorrectly-computed-txid-s-expected-s","errorCode":null,"errorMessage":"incorrectly computed txid '%s' -- expected '%s'","messagePattern":"incorrectly computed txid '(.+?)' -- expected '(.+?)'","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"core/endorser/msgvalidation.go","lineNumber":158,"sourceCode":"\n\t// ensure the epoch is 0\n\tif up.ChannelHeader.Epoch != 0 {\n\t\treturn errors.Errorf(\"epoch is non-zero\")\n\t}\n\n\t// ensure that there is a nonce\n\tif len(up.SignatureHeader.Nonce) == 0 {\n\t\treturn errors.Errorf(\"nonce is empty\")\n\t}\n\n\t// ensure that there is a creator\n\tif len(up.SignatureHeader.Creator) == 0 {\n\t\treturn errors.New(\"creator is empty\")\n\t}\n\n\texpectedTxID := protoutil.ComputeTxID(up.SignatureHeader.Nonce, up.SignatureHeader.Creator)\n\tif up.TxID() != expectedTxID {\n\t\treturn errors.Errorf(\"incorrectly computed txid '%s' -- expected '%s'\", up.TxID(), expectedTxID)\n\t}\n\n\tif up.SignedProposal.ProposalBytes == nil {\n\t\treturn errors.Errorf(\"empty proposal bytes\")\n\t}\n\n\tif up.SignedProposal.Signature == nil {\n\t\treturn errors.Errorf(\"empty signature bytes\")\n\t}\n\n\t// get the identity of the creator\n\tcreator, err := idDeserializer.DeserializeIdentity(up.SignatureHeader.Creator)\n\tif err != nil {\n\t\tlogger.Warnw(\"access denied\", \"error\", err, \"identity\", protoutil.LogMessageForSerializedIdentity(up.SignatureHeader.Creator))\n\t\treturn errors.Errorf(\"access denied: channel [%s] creator org unknown, creator is malformed\", up.ChannelID())\n\t}\n\n\tgenericAuthError := errors.Errorf(\"access denied: channel [%s] creator org [%s]\", up.ChannelID(), creator.GetMSPIdentifier())","sourceCodeStart":140,"sourceCodeEnd":176,"githubUrl":"https://github.com/hyperledger/fabric/blob/2736b63f8fd5932511d56fe68b7039d15977f7f6/core/endorser/msgvalidation.go#L140-L176","documentation":"The TxID embedded in the ChannelHeader must equal protoutil.ComputeTxID(nonce, creator), i.e. the SHA-256 hash of nonce concatenated with creator. This binds the transaction ID to the authentication material and prevents ID spoofing or replay under a different ID. A mismatch means the client computed or copied the TxID incorrectly.","triggerScenarios":"ProcessProposal -> preProcess -> Validate on a SignedProposal where ChannelHeader.TxId differs from ComputeTxID(SignatureHeader.Nonce, SignatureHeader.Creator) — e.g. TxID reused from a previous tx, nonce regenerated after TxID computation, or TxID computed with a different hash/concat order.","commonSituations":"Custom clients that compute TxID themselves (wrong algorithm or wrong field order), retry logic that refreshes the nonce but not the TxID, clients copying TxIDs from gateway logs, Fabric upgrade changing ComputeTxID expectations (sha256).","solutions":["Recompute TxID with protoutil.ComputeTxID(nonce, creator) (sha256(nonce || creator), hex-encoded) at proposal-build time.","Generate the nonce and compute the TxID in the same code path so they stay in sync; never reuse a TxID across proposals.","Prefer SDK proposal builders which guarantee TxID/nonce consistency."],"exampleFix":"// before\nnonce := randomNonce()\ntxid := previousTxid // reused\n// after\nnonce := randomNonce()\ntxid := protoutil.ComputeTxID(nonce, creator)","handlingStrategy":"validation","validationCode":"expected := protoutil.ComputeTxID(shdr.Nonce, shdr.Creator)\nif hdr.TxId != expected {\n    return fmt.Errorf(\"txid mismatch: got %s want %s\", hdr.TxId, expected)\n}","typeGuard":"func txidMatches(h *common.ChannelHeader, sh *common.SignatureHeader) bool {\n    return h != nil && sh != nil && h.TxId == protoutil.ComputeTxID(sh.Nonce, sh.Creator)\n}","tryCatchPattern":null,"preventionTips":["Compute TxID from the exact nonce+creator in the same builder function","Never reuse or hardcode TxIDs","On retry, regenerate nonce and TxID together"],"tags":["hyperledger-fabric","endorser","txid","integrity-check"],"backgroundTag":"txid-mismatch","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"}