{"record":{"id":"a9be3550dba64f02","repo":"hyperledger/fabric","slug":"empty-block-a9be35","errorCode":null,"errorMessage":"empty block","messagePattern":"empty block","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"core/handlers/validation/builtin/default_validation.go","lineNumber":58,"sourceCode":"\tTxValidatorV2_0 TransactionValidator\n}\n\n//go:generate mockery -dir . -name TransactionValidator -case underscore -output mocks/\ntype TransactionValidator interface {\n\tValidate(block *common.Block, namespace string, txPosition int, actionPosition int, policy []byte) commonerrors.TxValidationError\n}\n\nfunc (v *DefaultValidation) Validate(block *common.Block, namespace string, txPosition int, actionPosition int, contextData ...validation.ContextDatum) error {\n\tif len(contextData) == 0 {\n\t\tlogger.Panicf(\"Expected to receive policy bytes in context data\")\n\t}\n\n\tserializedPolicy, isSerializedPolicy := contextData[0].(vp.SerializedPolicy)\n\tif !isSerializedPolicy {\n\t\tlogger.Panicf(\"Expected to receive a serialized policy in the first context data\")\n\t}\n\tif block == nil || block.Data == nil {\n\t\treturn errors.New(\"empty block\")\n\t}\n\tif txPosition >= len(block.Data.Data) {\n\t\treturn errors.Errorf(\"block has only %d transactions, but requested tx at position %d\", len(block.Data.Data), txPosition)\n\t}\n\tif block.Header == nil {\n\t\treturn errors.Errorf(\"no block header\")\n\t}\n\n\tvar err error\n\tswitch {\n\tcase v.Capabilities.V2_0Validation():\n\t\terr = v.TxValidatorV2_0.Validate(block, namespace, txPosition, actionPosition, serializedPolicy.Bytes())\n\n\tcase v.Capabilities.V1_3Validation():\n\t\terr = v.TxValidatorV1_3.Validate(block, namespace, txPosition, actionPosition, serializedPolicy.Bytes())\n\n\tcase v.Capabilities.V1_2Validation():\n\t\tfallthrough","sourceCodeStart":40,"sourceCodeEnd":76,"githubUrl":"https://github.com/hyperledger/fabric/blob/2736b63f8fd5932511d56fe68b7039d15977f7f6/core/handlers/validation/builtin/default_validation.go#L40-L76","documentation":"The builtin default validation plugin's Validate inspects the block given by the committer, expecting a non-nil block with non-nil Data. It returns 'empty block' when the block itself or its Data payload is nil, i.e. there is nothing to validate.","triggerScenarios":"Validate (called by the committer's validation path, TestErrorConversion, TestValidateBadInput) is invoked with block == nil or block.Data == nil, or contextData[0] is not a serialized policy (that case panics instead), during block commit validation.","commonSituations":"A bug in the committer delivering malformed blocks; corrupted block storage after crash; test harness invoking the plugin with fabricated/nil blocks; ledger state issues after an unclean shutdown.","solutions":["Inspect the peer log around commit time to find which component supplied the nil/empty block","Run ledger integrity checks (peer node rebuild-dbs or restore from a good snapshot/backup)","Fix the calling test/harness to pass a constructed common.Block with Data populated","Report or fix upstream if the committer can legitimately produce nil blocks"],"exampleFix":"// before: test passes a bare block\nerr := validator.Validate(&common.Block{}, \"ns\", 0, 0, policy) // empty block\n// after: include Data and Header\nblock := &common.Block{Header: &common.BlockHeader{}, Data: &common.BlockData{Data: [][]byte{envelopeBytes}}}\nerr := validator.Validate(block, \"ns\", 0, 0, policy)","handlingStrategy":"validation","validationCode":"func validateBlockInput(block *common.Block, ns string, txPos, actionPos int) error {\n    if block == nil || block.Data == nil {\n        return errors.New(\"empty block: refusing validation\")\n    }\n    return nil\n}\n// call before plugin.Validate(...)","typeGuard":"func hasBlockData(b *common.Block) bool {\n    return b != nil && b.Data != nil\n}","tryCatchPattern":"if err := v.Validate(block, ns, txPos, actionPos, policy); err != nil {\n    if err.Error() == \"empty block\" {\n        logger.Errorf(\"committer supplied empty block; check ledger integrity\")\n    }\n    return err\n}","preventionTips":["Guard tests to always construct Header and Data","Investigate storage integrity if the committer yields nil blocks","Use peer node rebuild-dbs after unclean crashes","Never fabricate bare common.Block{} in harnesses"],"tags":["fabric","validation-plugin","block-validation","committer","nil-block"],"backgroundTag":"empty-block-validation","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"}