{"record":{"id":"bf8b8f53ca52b201","repo":"hyperledger/fabric","slug":"transaction-d-has-no-payload","errorCode":null,"errorMessage":"transaction %d has no payload","messagePattern":"transaction (.+?) has no payload","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"protoutil/blockutils.go","lineNumber":334,"sourceCode":"func VerifyTransactionsAreWellFormed(bd *cb.BlockData) error {\n\tif bd == nil || bd.Data == nil || len(bd.Data) == 0 {\n\t\treturn errors.New(\"empty block\")\n\t}\n\n\t// If we have a single transaction, and the block is a config block, then no need to check\n\t// well formed-ness, because there cannot be another transaction in the original block.\n\tif HasConfigTx(bd) {\n\t\treturn nil\n\t}\n\n\tfor i, rawTx := range bd.Data {\n\t\tenv := &cb.Envelope{}\n\t\tif err := proto.Unmarshal(rawTx, env); err != nil {\n\t\t\treturn fmt.Errorf(\"transaction %d is invalid: %v\", i, err)\n\t\t}\n\n\t\tif len(env.Payload) == 0 {\n\t\t\treturn fmt.Errorf(\"transaction %d has no payload\", i)\n\t\t}\n\n\t\tif len(env.Signature) == 0 {\n\t\t\treturn fmt.Errorf(\"transaction %d has no signature\", i)\n\t\t}\n\n\t\texpected, err := proto.Marshal(env)\n\t\tif err != nil {\n\t\t\treturn fmt.Errorf(\"failed re-marshaling envelope: %v\", err)\n\t\t}\n\n\t\tif len(expected) < len(rawTx) {\n\t\t\treturn fmt.Errorf(\"transaction %d has %d trailing bytes\", i, len(rawTx)-len(expected))\n\t\t}\n\t\tif !bytes.Equal(expected, rawTx) {\n\t\t\treturn fmt.Errorf(\"transaction %d (%s) does not match its raw form (%s)\", i,\n\t\t\t\tbase64.StdEncoding.EncodeToString(expected), base64.StdEncoding.EncodeToString(rawTx))\n\t\t}","sourceCodeStart":316,"sourceCodeEnd":352,"githubUrl":"https://github.com/hyperledger/fabric/blob/2736b63f8fd5932511d56fe68b7039d15977f7f6/protoutil/blockutils.go#L316-L352","documentation":"VerifyTransactionsAreWellFormed validates each entry in a block's Data field by unmarshaling it into a common.Envelope. After a successful proto.Unmarshal, it checks that env.Payload is non-empty; a zero-length Payload means the envelope is structurally present but carries no transaction payload, so the block cannot be hashed/verified meaningfully. The library throws this to fail fast on corrupt or malformed block data rather than propagating an empty payload downstream.","triggerScenarios":"Calling BlockDataHash (directly or indirectly) on a block whose Data contains an entry that unmarshals to an Envelope with len(env.Payload)==0 — e.g. a truncated, hand-crafted, or wrongly marshaled transaction at index i.","commonSituations":"Processing a corrupted or externally produced genesis/application block; writing blocks with test helpers that append raw bytes instead of marshaled envelopes; deserializing blocks from an untrusted or buggy source; block storage truncation after a crash.","solutions":["Inspect block.Data.Data[i] and confirm the envelope was produced with protoutil.Marshal/MarshalOrPanic of a fully populated common.Envelope (Payload and Signature set).","Regenerate or re-fetch the block from a trusted peer/orderer instead of using the corrupt copy.","In block-producing code, reject envelopes with empty Payload before adding them to a block.","Log the offending index and dump base64 of the raw bytes to compare against a known-good envelope."],"exampleFix":"// before: appending raw, possibly empty payload\nenv := &cb.Envelope{Signature: sig}\nraw, _ := proto.Marshal(env)\n// after\nif len(env.Payload) == 0 {\n\treturn errors.New(\"refusing to create envelope with empty payload\")\n}\nraw, _ := proto.Marshal(env)","handlingStrategy":"validation","validationCode":"for i, rawTx := range block.Data.Data {\n\tenv := &cb.Envelope{}\n\tif err := proto.Unmarshal(rawTx, env); err != nil { return err }\n\tif len(env.Payload) == 0 {\n\t\treturn fmt.Errorf(\"tx %d: empty payload, skipping block\", i)\n\t}\n}","typeGuard":"func hasPayload(env *cb.Envelope) bool { return env != nil && len(env.Payload) > 0 }","tryCatchPattern":null,"preventionTips":["Always build envelopes via protoutil helpers rather than hand-assembling bytes.","Validate envelope contents before inserting into a block.","Check block provenance; never trust externally generated block files.","Log the offending transaction index when validation fails."],"tags":["hyperledger-fabric","protobuf","block-validation"],"backgroundTag":"malformed-envelope-payload","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"}