{"record":{"id":"116fbf046c03fa1b","repo":"hyperledger/fabric","slug":"block-hashes-not-maintained-in-index","errorCode":null,"errorMessage":"block hashes not maintained in index","messagePattern":"block hashes not maintained in index","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"common/ledger/blkstorage/blockindex.go","lineNumber":156,"sourceCode":"\t\t}\n\t}\n\n\tbatch.Put(indexSavePointKey, encodeBlockNum(blockIdxInfo.blockNum))\n\t// Setting snyc to true as a precaution, false may be an ok optimization after further testing.\n\tif err := index.db.WriteBatch(batch, true); err != nil {\n\t\treturn err\n\t}\n\treturn nil\n}\n\nfunc (index *blockIndex) isAttributeIndexed(attribute IndexableAttr) bool {\n\t_, ok := index.indexItemsMap[attribute]\n\treturn ok\n}\n\nfunc (index *blockIndex) getBlockLocByHash(blockHash []byte) (*fileLocPointer, error) {\n\tif !index.isAttributeIndexed(IndexableAttrBlockHash) {\n\t\treturn nil, errors.New(\"block hashes not maintained in index\")\n\t}\n\tb, err := index.db.Get(constructBlockHashKey(blockHash))\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\tif b == nil {\n\t\treturn nil, errors.Errorf(\"no such block hash [%x] in index\", blockHash)\n\t}\n\tblkLoc := &fileLocPointer{}\n\tif err := blkLoc.unmarshal(b); err != nil {\n\t\treturn nil, err\n\t}\n\treturn blkLoc, nil\n}\n\nfunc (index *blockIndex) getBlockLocByBlockNum(blockNum uint64) (*fileLocPointer, error) {\n\tif !index.isAttributeIndexed(IndexableAttrBlockNum) {\n\t\treturn nil, errors.New(\"block numbers not maintained in index\")","sourceCodeStart":138,"sourceCodeEnd":174,"githubUrl":"https://github.com/hyperledger/fabric/blob/2736b63f8fd5932511d56fe68b7039d15977f7f6/common/ledger/blkstorage/blockindex.go#L138-L174","documentation":"getBlockLocByHash returns this sentinel error when the block index was configured without IndexableAttrBlockHash, meaning the store never wrote blockHash->location index entries. Retrieving a block by hash is therefore unsupported by the current index configuration; it is not an IO failure but a capability/configuration check via isAttributeIndexed.","triggerScenarios":"Calling GetBlockByHash (retrieveBlockByHash -> getBlockLocByHash) on a block store whose ledger config omitted blockHash from index items (e.g. IndexConfig.Attributes not including IndexableAttrBlockHash).","commonSituations":"Deployments that trimmed indexable attributes for performance and later queried by hash; copied ledgersData from an instance configured differently; tests/tools assuming the default full index.","solutions":["Enable block-hash indexing: include IndexableAttrBlockHash in the blkstorage index config (ledger.blockIndex or IndexConfig.Attributes) and restart.","If the index was created without it, existing blocks must be re-indexed (syncIndex/index replay) or the ledger re-synced from peers/orderers so the hash entries are written.","Change the application to look up blocks by number or txID instead of hash when hash indexing is intentionally disabled.","Verify the effective ledger config on the running peer (core.yaml ledger -> blockIndex) matches expectations before diagnosing further."],"exampleFix":"// before: core.yaml\nledger:\n  blockIndex:\n    # hash lookups fail: block hashes not maintained in index\n// after: use default (all attributes indexed)\nledger:\n  blockIndex:\n    maxBatchSize: 10  # omitting index-attr overrides keeps full index incl. block hash","handlingStrategy":"validation","validationCode":"// Go: confirm hash indexing is enabled before calling GetBlockByHash\nfunc hashIndexEnabled(cfg blkstorage.IndexConfig) bool {\n\tfor _, a := range cfg.Attributes {\n\t\tif a == blkstorage.IndexableAttrBlockHash {\n\t\t\treturn true\n\t\t}\n\t}\n\treturn false\n}","typeGuard":null,"tryCatchPattern":"// Go: fall back to a linear scan by number when hash lookup is unsupported\nblock, err := store.RetrieveBlockByHash(hash)\nif err != nil {\n\tif strings.Contains(err.Error(), \"block hashes not maintained in index\") {\n\t\t// fall back: iterate RetrieveBlocks and compare Header.DataHash\n\t} else {\n\t\treturn err\n\t}\n}","preventionTips":["Keep the default full block index (all IndexableAttr values) unless profiling proves otherwise.","When trimming index attributes, document which query APIs become unavailable.","Match index configuration across peers sharing/replicating ledgersData.","Add a startup self-check that queries by hash once and warns if disabled."],"tags":["configuration","index","ledger","unsupported-operation"],"backgroundTag":"feature-not-enabled","analyzedSha":"2736b63f8fd5932511d56fe68b7039d15977f7f6","analyzedAt":"2026-09-04T08:52:36.465Z","contentChangedAt":"2026-09-04T08:52:36.465Z","schemaVersion":2},"datasetVersion":"2026-09-08T15:18:49.778Z"}