{"record":{"id":"910b80095d20d71b","repo":"hyperledger/fabric","slug":"invalid-txidkey-x-unexpected-prefix","errorCode":null,"errorMessage":"invalid txIDKey {%x} - unexpected prefix","messagePattern":"invalid txIDKey (.+?) - unexpected prefix","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"common/ledger/blkstorage/blockindex.go","lineNumber":432,"sourceCode":"\nfunc constructTxIDKey(txID string, blkNum, txNum uint64) []byte {\n\tk := append(\n\t\t[]byte{txIDIdxKeyPrefix},\n\t\tutil.EncodeOrderPreservingVarUint64(uint64(len(txID)))...,\n\t)\n\tk = append(k, txID...)\n\tk = append(k, util.EncodeOrderPreservingVarUint64(blkNum)...)\n\treturn append(k, util.EncodeOrderPreservingVarUint64(txNum)...)\n}\n\n// retrieveTxID takes input an encoded txid key of the format `prefix:len(TxID):TxID:BlkNum:TxNum`\n// and returns the TxID from this\nfunc retrieveTxID(encodedTxIDKey []byte) (string, error) {\n\tif len(encodedTxIDKey) == 0 {\n\t\treturn \"\", errors.New(\"invalid txIDKey - zero-length slice\")\n\t}\n\tif encodedTxIDKey[0] != txIDIdxKeyPrefix {\n\t\treturn \"\", errors.Errorf(\"invalid txIDKey {%x} - unexpected prefix\", encodedTxIDKey)\n\t}\n\tremainingBytes := encodedTxIDKey[utf8.RuneLen(txIDIdxKeyPrefix):]\n\n\ttxIDLen, n, err := util.DecodeOrderPreservingVarUint64(remainingBytes)\n\tif err != nil {\n\t\treturn \"\", errors.WithMessagef(err, \"invalid txIDKey {%x}\", encodedTxIDKey)\n\t}\n\tremainingBytes = remainingBytes[n:]\n\tif len(remainingBytes) <= int(txIDLen) {\n\t\treturn \"\", errors.Errorf(\"invalid txIDKey {%x}, fewer bytes present\", encodedTxIDKey)\n\t}\n\treturn string(remainingBytes[:int(txIDLen)]), nil\n}\n\nfunc retrieveBlockNum(encodedTxIDKey []byte, BlkNumStartingIndex int) (uint64, error) {\n\tn, _, err := util.DecodeOrderPreservingVarUint64(encodedTxIDKey[BlkNumStartingIndex:])\n\treturn n, err\n}","sourceCodeStart":414,"sourceCodeEnd":450,"githubUrl":"https://github.com/hyperledger/fabric/blob/2736b63f8fd5932511d56fe68b7039d15977f7f6/common/ledger/blkstorage/blockindex.go#L414-L450","documentation":"retrieveTxID requires encoded keys to start with the txID index prefix byte. If the first byte does not match txIDIdxKeyPrefix, the key is not a txID key and this error reports the raw bytes in hex. It protects the decoder from reading foreign or corrupted index entries.","triggerScenarios":"An iterator range spanning unintended keys, a corrupted index DB whose keys lost their prefix byte, or direct calls (including tests) with wrongly-prefixed byte slices.","commonSituations":"Index DB corruption after unclean shutdown or partial file copy; someone manually manipulating the leveldb files; decoder tests exercising invalid input.","solutions":["Verify the key source — only keys from the txID index range (txIDIdxKeyPrefix to prefix+1) should reach this function.","If production keys lack the prefix, treat the index as corrupted and rebuild the block index.","Fix the calling code to construct keys with constructTxIDKey so the prefix is always present."],"exampleFix":null,"handlingStrategy":"validation","validationCode":"if len(key) == 0 || key[0] != txIDIdxKeyPrefix {\n    return \"\", errors.Errorf(\"not a txID key: %x\", key)\n}","typeGuard":"func hasTxIDKeyPrefix(k []byte) bool {\n    return len(k) > 0 && k[0] == txIDIdxKeyPrefix\n}","tryCatchPattern":"txID, err := retrieveTxID(key)\nif err != nil && strings.Contains(err.Error(), \"unexpected prefix\") {\n    return fmt.Errorf(\"index key %x is not a txID key — suspect index corruption: %w\", key, err)\n}\nif err != nil { return err }","preventionTips":["Only feed retrieveTxID keys sourced from the txID index range iterator.","Construct keys exclusively via constructTxIDKey so the prefix is always present.","Never hand-edit or manually copy leveldb files while the peer is running."],"tags":["ledger","blockstorage","decoding","corruption"],"backgroundTag":"invalid-index-key-format","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"}