{"record":{"id":"915dac65f42587a4","repo":"FuelLabs/fuel-core","slug":"while-getting-receipts-for-tx-id","errorCode":null,"errorMessage":"while getting receipts for tx_id: {:?}","messagePattern":"while getting receipts for tx_id: (.+?)","errorType":"exception","errorClass":"Error::DB","httpStatus":null,"severity":"error","filePath":"crates/services/block_aggregator_api/src/blocks/old_block_source.rs","lineNumber":156,"sourceCode":"                Some(tx) => {\n                    tracing::debug!(\"found tx id: {:?}\", tx_id);\n                    txs.push(tx.into_owned());\n                }\n                None => {\n                    return Ok(vec![]);\n                }\n            }\n        }\n        Ok(txs)\n    }\n\n    fn get_receipts(&self, tx_ids: &[TxId]) -> Result<Vec<Vec<Receipt>>> {\n        use itertools::Itertools;\n        tx_ids\n            .iter()\n            .map(|tx_id| {\n                self.receipts.get_receipts(tx_id).map_err(|err| {\n                    Error::DB(anyhow::anyhow!(err).context(format!(\n                        \"while getting receipts for tx_id: {:?}\",\n                        tx_id\n                    )))\n                })\n            })\n            .try_collect()\n    }\n}\n\nimpl<Convertor, DB, Receipts> Iterator for StorageIterator<Convertor, DB, Receipts>\nwhere\n    DB: StorageInspect<FuelBlocks, Error = StorageError>,\n    DB: StorageInspect<Transactions, Error = StorageError>,\n    Receipts: TxReceipts,\n    Convertor: BlockConverter,\n{\n    type Item = Result<(BlockHeight, Convertor::Block)>;\n","sourceCodeStart":138,"sourceCodeEnd":174,"githubUrl":"https://github.com/FuelLabs/fuel-core/blob/b9d4d170da3a31c9ace5f963d633b326348e0d42/crates/services/block_aggregator_api/src/blocks/old_block_source.rs#L138-L174","documentation":"Thrown by the block aggregator API's old-block source while streaming historical blocks: for each transaction in a block, StorageIterator::get_receipts calls the configured TxReceipts provider, and any failure is wrapped into Error::DB with the failing tx_id attached as context (crates/services/block_aggregator_api/src/blocks/old_block_source.rs:156). The error becomes an Err item in the iterator returned by blocks_starting_from, so block streaming stops at the height whose receipts cannot be read. The anyhow context preserves the underlying storage error as root cause.","triggerScenarios":"Calling blocks_starting_from(height) (directly or via the aggregator's block-serving loop) when the receipts provider fails for one of the block's tx_ids: receipts table missing or pruned for that range, database handle closed or unopened, IO/corruption error inside the provider, or a test stub TxReceipts implementation that returns Err.","commonSituations":"Node restored from a pruned/partial snapshot that lacks receipt data; underlying DB (e.g. RocksDB) opened with an incompatible column-family layout by a different fuel-core version; disk or IO failures mid-stream; custom Receipts adapters in tests or plugins that error instead of returning data.","solutions":["Take the tx_id from the message and probe the receipts storage directly for that key to confirm whether the data exists or the read itself fails.","Inspect the inner error chain (the anyhow context keeps the root cause) to distinguish 'not found' from IO/lock errors, and fix the storage layer accordingly.","Verify the node version matches the version that produced the database snapshot and that receipts were not pruned; re-sync the range if data is absent.","For transient IO/lock failures, restart the stream from the failing height (the iterator stops on Err, so restart rather than continue).","If your protocol tolerates gaps, skip the affected height explicitly; the iterator itself will not advance past an Err item."],"exampleFix":"// before: stream until it silently stops on the first Err\nfor item in source.blocks_starting_from(start) {\n    let (height, block) = item?;\n    publish(height, block);\n}\n\n// after: surface DB receipt failures with height and retry from the same height\nlet mut height = start;\n'outer: loop {\n    for item in source.blocks_starting_from(height) {\n        match item {\n            Ok((h, block)) => { publish(h, block); height = h.succ().unwrap_or(h); }\n            Err(Error::DB(ctx)) => {\n                tracing::error!(%ctx, from = ?height, \"receipts unavailable\");\n                continue 'outer; // retry stream at same height after fixing storage\n            }\n            Err(e) => break 'outer,\n        }\n    }\n    break;\n}","handlingStrategy":"retry","validationCode":"// Before starting the stream, verify receipts are readable for the start height's block\nuse fuel_core_storage::StorageInspect;\nuse fuel_core_types::fuel_tx::TxId;\n\nfn receipts_available<R: TxReceipts>(receipts: &R, tx_ids: &[TxId]) -> bool {\n    tx_ids.iter().all(|id| receipts.get_receipts(id).is_ok())\n}","typeGuard":null,"tryCatchPattern":"match source.blocks_starting_from(height).next() {\n    Some(Ok((h, block))) => { /* forward block */ }\n    Some(Err(Error::DB(ctx))) => {\n        tracing::error!(%ctx, from = ?height, \"receipts unavailable\");\n        // restart stream at the same height after fixing/backing off; do not silently skip\n        restart_stream_at(height);\n    }\n    Some(Err(other)) => return Err(other),\n    None => { /* stream end */ }\n}","preventionTips":["Sync or restore the full database (including receipts) before serving old blocks; never point the old-block source at a pruned snapshot.","Run producer and consumer nodes on the same fuel-core version so storage layouts match.","Wrap the TxReceipts implementation with logging so the root cause (IO vs not-found vs closed handle) is recorded before the Error::DB wrap.","Monitor the stream for Err items and alert instead of letting iteration stop silently."],"tags":["rust","fuel-core","database","receipts","block-aggregator"],"backgroundTag":null,"analyzedSha":"b9d4d170da3a31c9ace5f963d633b326348e0d42","analyzedAt":"2026-08-16T08:56:42.692Z","schemaVersion":2},"datasetVersion":"2026-08-16T13:17:31.715Z"}