{"record":{"id":"c0a4a3fb2e570ecc","repo":"hyperledger/fabric","slug":"transaction-d-is-invalid-v","errorCode":null,"errorMessage":"transaction %d is invalid: %v","messagePattern":"transaction (.+?) is invalid: (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"protoutil/blockutils.go","lineNumber":330,"sourceCode":"\t}\n\treturn nil\n}\n\nfunc 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}","sourceCodeStart":312,"sourceCodeEnd":348,"githubUrl":"https://github.com/hyperledger/fabric/blob/2736b63f8fd5932511d56fe68b7039d15977f7f6/protoutil/blockutils.go#L312-L348","documentation":"VerifyTransactionsAreWellFormed iterates the block's data envelopes and proto-unmarshals each into cb.Envelope. If any envelope fails to parse, it returns this error naming the transaction index and the underlying parse failure, identifying the exact corrupt entry in the block.","triggerScenarios":"Calling VerifyTransactionsAreWellFormed on a block where Data[i] bytes are not a valid protobuf Envelope — truncated writes, corrupted ledger segments, or a producer writing non-envelope payloads.","commonSituations":"Disk corruption on file-ledger nodes, blocks truncated during snapshot/restore, or a misbehaving ordering node emitting malformed envelopes.","solutions":["Identify which data source produced the block and re-fetch the block from a healthy ordering node or peer","Run ledger integrity checks / rebuild the ledger if many blocks fail the same way","Verify storage health (disk, filesystem) when corruption is recurring","If the corruption came from a restore/migration, redo it from a verified backup"],"exampleFix":"// before\nenv := &cb.Envelope{}\nif err := proto.Unmarshal(rawTx, env); err != nil {\n    return fmt.Errorf(\"transaction %d is invalid: %v\", i, err)\n}\n// after\nenv := &cb.Envelope{}\nif err := proto.Unmarshal(rawTx, env); err != nil {\n    return fmt.Errorf(\"transaction %d (len %d) is invalid: %v\", i, len(rawTx), err)\n}\nif len(rawTx) == 0 {\n    return fmt.Errorf(\"transaction %d is empty\", i)\n}","handlingStrategy":"validation","validationCode":"for i, rawTx := range block.Data.Data {\n    probe := &cb.Envelope{}\n    if len(rawTx) == 0 || proto.Unmarshal(rawTx, probe) != nil {\n        return fmt.Errorf(\"envelope %d in block %d is corrupt\", i, block.GetHeader().GetNumber())\n    }\n}\nerr := VerifyTransactionsAreWellFormed(block.Data)","typeGuard":"func isParseableEnvelope(raw []byte) (*cb.Envelope, bool) {\n    env := &cb.Envelope{}\n    if len(raw) == 0 || proto.Unmarshal(raw, env) != nil || len(env.GetPayload()) == 0 {\n        return nil, false\n    }\n    return env, true\n}","tryCatchPattern":"if err := VerifyTransactionsAreWellFormed(block.Data); err != nil {\n    logger.Errorf(\"corrupt transactions detected: %v — re-fetching block\", err)\n    return refetchBlock(block.GetHeader().GetNumber())\n}","preventionTips":["Monitor disk/filesystem health on ledger hosts","Checksum blocks during snapshot/restore and migration","Reject blocks with unparseable envelopes instead of propagating them","Rebuild the ledger from a trusted orderer when multiple transactions fail to parse"],"tags":["protobuf","unmarshal","transaction","corruption"],"backgroundTag":"protobuf-unmarshal-failed","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"}