{"record":{"id":"d4febdeb617c2ea9","repo":"hyperledger/fabric","slug":"cannot-create-a-block-deliverer-because-height-0","errorCode":null,"errorMessage":"cannot create a block deliverer because height=0","messagePattern":"cannot create a block deliverer because height=0","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"core/deliverservice/deliveryclient.go","lineNumber":175,"sourceCode":"\n\tgo func() {\n\t\td.blockDeliverer.DeliverBlocks()\n\t\tfinalizer()\n\t}()\n\treturn nil\n}\n\nfunc (d *deliverServiceImpl) createBlockDelivererCFT(chainID string, ledgerInfo blocksprovider.LedgerInfo) (*blocksprovider.Deliverer, error) {\n\theight, err := ledgerInfo.LedgerHeight()\n\tif err != nil {\n\t\treturn nil, errors.Wrapf(err, \"cannot get ledger height\")\n\t}\n\tcurrentBlockHash, err := ledgerInfo.GetCurrentBlockHash()\n\tif err != nil {\n\t\treturn nil, errors.Wrapf(err, \"cannot get current block hash\")\n\t}\n\tif height == 0 {\n\t\treturn nil, errors.New(\"cannot create a block deliverer because height=0\")\n\t}\n\tubv, err := deliverclient.NewBlockVerificationAssistantFromConfig(\n\t\td.conf.ChannelConfig, height-1, currentBlockHash, chainID, d.conf.CryptoProvider, flogging.MustGetLogger(\"common.deliverclient.blockverification\"),\n\t)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\tlogger.Debugf(\"Created an updatable block verifier from ChannelConfig, height: %d,`%+v`\", height, ubv)\n\n\tlogger.Infof(\"Creating a CFT (crash fault tolerant) BlockDeliverer for channel `%s`\", chainID)\n\tdc := &blocksprovider.Deliverer{\n\t\tChannelID: chainID,\n\t\tBlockHandler: &GossipBlockHandler{\n\t\t\tgossip:              d.conf.Gossip,\n\t\t\tblockGossipDisabled: !d.conf.DeliverServiceConfig.BlockGossipEnabled,\n\t\t\tlogger:              flogging.MustGetLogger(\"peer.blocksprovider\").With(\"channel\", chainID),\n\t\t},\n\t\tLedger:                 ledgerInfo,","sourceCodeStart":157,"sourceCodeEnd":193,"githubUrl":"https://github.com/hyperledger/fabric/blob/2736b63f8fd5932511d56fe68b7039d15977f7f6/core/deliverservice/deliveryclient.go#L157-L193","documentation":"createBlockDelivererCFT builds a crash-fault-tolerant block deliverer for a channel and requires the local ledger to be initialized. Before constructing the deliverer it reads the ledger height via blocksprovider.LedgerInfo.LedgerHeight(); if the ledger reports height 0 (no genesis block committed yet) there is no block to seek from, so it refuses to create a deliverer. This is a deliberate guard: the deliver service must know a starting block/hash to connect to an ordering service.","triggerScenarios":"Calling StartDeliverForChannel (which calls createBlockDelivererCFT) while the peer's ledger for that channel has LedgerHeight() == 0 — i.e. the channel's genesis block has not been joined/committed on this peer.","commonSituations":"Peer started before joining the channel; genesis block join transaction failed or was retried; peer storage (ledger data) was wiped or partially restored so the channel exists in config but the ledger is empty; a race where delivery is started immediately after channel creation before the genesis commit lands.","solutions":["Ensure the peer has joined the channel: commit the genesis block (peer channel join) and verify the ledger height is >= 1 before starting delivery","Wait/retry delivery startup until the ledger is initialized (height >= 1) instead of starting it immediately after channel creation","Check the peer logs and ledger data directory for corruption or an incomplete join; if damaged, re-join the channel from the genesis block","If the ledger is empty because of a restore, restore the ledger data (or re-join and let gossip/state sync catch up) before enabling the deliver service"],"exampleFix":"// before: start deliver as soon as channel is known\nsvc.StartDeliverForChannel(chainID, \"myclient\", identity)\n\n// after: wait for the ledger to be initialized\nfor {\n  h, err := ledgerInfo.LedgerHeight()\n  if err == nil && h > 0 {\n    break\n  }\n  time.Sleep(time.Second)\n}\nsvc.StartDeliverForChannel(chainID, \"myclient\", identity)","handlingStrategy":"validation","validationCode":"height, err := ledgerInfo.LedgerHeight()\nif err != nil {\n    return fmt.Errorf(\"ledger not readable for %s: %w\", chainID, err)\n}\nif height == 0 {\n    return fmt.Errorf(\"channel %s ledger empty; join genesis block before starting delivery\", chainID)\n}","typeGuard":"func ledgerReady(h uint64, err error) bool {\n    return err == nil && h > 0\n}","tryCatchPattern":"err := deliverSvc.StartDeliverForChannel(chainID, clientName, identity)\nif err != nil && strings.Contains(err.Error(), \"height=0\") {\n    // ledger not initialized; schedule retry after genesis commit\n}","preventionTips":["Always join the channel (commit genesis) before wiring the deliver service","Poll LedgerHeight() until >= 1 as a readiness gate","Alert on peers whose channel membership exists but ledger height stays 0","Avoid wiping ledger data directories without re-joining channels"],"tags":["hyperledger-fabric","ledger","deliver-service","ordering"],"backgroundTag":"ledger-height-zero","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"}