{"record":{"id":"3a7b31d96d26de62","repo":"hyperledger/fabric","slug":"nil-chaincodeid-in-header-extension-3a7b31","errorCode":null,"errorMessage":"nil ChaincodeId in header extension","messagePattern":"nil ChaincodeId in header extension","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"core/committer/txvalidator/v20/plugindispatcher/dispatcher.go","lineNumber":130,"sourceCode":"\t// get header extensions so we have the chaincode ID\n\thdrExt, err := protoutil.UnmarshalChaincodeHeaderExtension(chdr.Extension)\n\tif err != nil {\n\t\treturn peer.TxValidationCode_BAD_HEADER_EXTENSION, err\n\t}\n\n\t/* obtain the list of namespaces we're writing to */\n\trespPayload, err := protoutil.GetActionFromEnvelope(envBytes)\n\tif err != nil {\n\t\treturn peer.TxValidationCode_BAD_RESPONSE_PAYLOAD, errors.WithMessage(err, \"GetActionFromEnvelope failed\")\n\t}\n\ttxRWSet := &rwsetutil.TxRwSet{}\n\tif err = txRWSet.FromProtoBytes(respPayload.Results); err != nil {\n\t\treturn peer.TxValidationCode_BAD_RWSET, errors.WithMessage(err, \"txRWSet.FromProtoBytes failed\")\n\t}\n\n\t// Verify the header extension and response payload contain the ChaincodeId\n\tif hdrExt.ChaincodeId == nil {\n\t\treturn peer.TxValidationCode_INVALID_OTHER_REASON, errors.New(\"nil ChaincodeId in header extension\")\n\t}\n\n\tif respPayload.ChaincodeId == nil {\n\t\treturn peer.TxValidationCode_INVALID_OTHER_REASON, errors.New(\"nil ChaincodeId in ChaincodeAction\")\n\t}\n\n\t// get name and version of the cc we invoked\n\tccID := hdrExt.ChaincodeId.Name\n\tccVer := respPayload.ChaincodeId.Version\n\n\t// sanity check on ccID\n\tif ccID == \"\" {\n\t\terr = errors.New(\"invalid chaincode ID\")\n\t\tlogger.Errorf(\"%+v\", err)\n\t\treturn peer.TxValidationCode_INVALID_CHAINCODE, err\n\t}\n\tif ccID != respPayload.ChaincodeId.Name {\n\t\terr = errors.Errorf(\"inconsistent ccid info (%s/%s)\", ccID, respPayload.ChaincodeId.Name)","sourceCodeStart":112,"sourceCodeEnd":148,"githubUrl":"https://github.com/hyperledger/fabric/blob/2736b63f8fd5932511d56fe68b7039d15977f7f6/core/committer/txvalidator/v20/plugindispatcher/dispatcher.go#L112-L148","documentation":"The v20 plugin dispatcher validates that both the header extension and the ChaincodeAction response payload carry a ChaincodeId before extracting name/version for validation. When the transaction's header extension has a nil ChaincodeId, the transaction is structurally malformed and is rejected with INVALID_OTHER_REASON. This guards against transactions that don't identify which chaincode they invoke.","triggerScenarios":"Dispatch (VSCC validation for the v20 tx validator plugin) parses a TxRWSet and inspects hdrExt.ChaincodeId — a proposal header extension without ChaincodeId reaches validation, e.g. a malformed or hand-crafted envelope.","commonSituations":"Buggy or low-level client SDK usage constructing proposals without ChaincodeId; malicious/fuzzed transaction submission; corrupted envelope bytes on the ordering path.","solutions":["Fix the client to always set ChaincodeId in the proposal header extension (use a maintained SDK)","Trace the offending transaction via peer logs/txId and inspect the envelope with configtxlator/inspect tools","Reject malformed proposals at the gateway/orderer before they reach blocks","Update SDK/Fabric versions if a known serialization bug produced nil ChaincodeId"],"exampleFix":"// before: manually built proposal missing ChaincodeId\nconst hdrExt = new HeaderExt(); hdrExt.ChaincodeId = null;\n// after\nconst hdrExt = new HeaderExt(); hdrExt.ChaincodeId = {name: 'mycc', version: '1.0'};","handlingStrategy":"validation","validationCode":"// client-side pre-check before signing/submitting\nif (!proposal.getHeader().getExtension().chaincodeId) throw new Error('missing ChaincodeId in header extension');","typeGuard":"function hasChaincodeId(hdrExt) {\n  return !!hdrExt && !!hdrExt.chaincodeId && !!hdrExt.chaincodeId.name;\n}","tryCatchPattern":"try { await gateway.submit(tx); } catch (e) {\n  if (String(e).includes('nil ChaincodeId in header extension')) { /* rebuild proposal via SDK, do not retry same envelope */ }\n}","preventionTips":["Build proposals only through maintained SDKs","Never submit raw/hand-crafted envelopes in production","Validate envelopes with configtxlator before submission"],"tags":["hyperledger-fabric","tx-validation","malformed-transaction","header-extension"],"backgroundTag":"malformed-transaction","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"}