{"record":{"id":"cea13539ec941e3a","repo":"FuelLabs/fuel-core","slug":"requested-block-height-is-greater-than-current","errorCode":null,"errorMessage":"Requested block height {} is greater than current synced height {}","messagePattern":"Requested block height (.+?) is greater than current synced height (.+?)","errorType":"validation","errorClass":"crate::result::Error","httpStatus":null,"severity":"error","filePath":"crates/services/block_aggregator_api/src/db/remote_cache.rs","lineNumber":164,"sourceCode":"    }\n}\n\nimpl<S> BlocksProvider for RemoteBlocksProvider<S>\nwhere\n    S: Send + Sync + 'static,\n    S: KeyValueInspect<Column = Column>,\n{\n    type Block = Arc<[u8]>;\n    type BlockRangeResponse = BlockRangeResponse;\n\n    fn get_block_range(\n        &self,\n        first: BlockHeight,\n        last: BlockHeight,\n    ) -> crate::result::Result<Self::BlockRangeResponse> {\n        let current_height = self.get_current_height()?.unwrap_or(BlockHeight::new(0));\n        if last > current_height {\n            Err(Error::db_error(anyhow!(\n                \"Requested block height {} is greater than current synced height {}\",\n                last,\n                current_height\n            )))\n        } else {\n            self.stream_blocks(first, last)\n        }\n    }\n\n    fn get_current_height(&self) -> crate::result::Result<Option<BlockHeight>> {\n        let height = self\n            .local_persisted\n            .as_structured_storage()\n            .storage_as_ref::<LatestBlock>()\n            .get(&())\n            .map_err(|e| {\n                Error::DB(anyhow!(e).context(\"while getting latest block height\"))\n            })?","sourceCodeStart":146,"sourceCodeEnd":182,"githubUrl":"https://github.com/FuelLabs/fuel-core/blob/b9d4d170da3a31c9ace5f963d633b326348e0d42/crates/services/block_aggregator_api/src/db/remote_cache.rs#L146-L182","documentation":"Raised by the remote block cache's get_block_range: the caller asked for blocks up to height `last`, but the locally persisted chain height is lower (or 0 when nothing is synced). Rather than returning a partial/empty range, the API fails with Error::db_error so callers notice they requested unsynced data.","triggerScenarios":"Calling get_block_range(first, last) with last > current synced height — e.g., querying the chain tip height from a fresher source (or a hardcoded/future height) while this cache has not caught up. Note: no synced data at all yields current_height = 0, so any last > 0 fails.","commonSituations":"Aggregator started before the source node finished syncing; a fetch loop using the tip from another endpoint; restart after the local cache was wiped; height mismatch between the remote source and local persisted state.","solutions":["Query get_current_height() first and clamp last to it (or last = min(last, current_height)) before requesting the range","If the cache is empty or stale, wait for or trigger the initial sync, then retry the range request","Drive range fetches from this cache's own current height, not from an external tip estimate","If a true catch-up fetch is intended, use the stream_blocks path or an API that tolerates unsynced tails instead of get_block_range"],"exampleFix":"// before\nlet resp = source.get_block_range(first, requested_last)?; // fails when requested_last > synced\n\n// after\nlet current = source.get_current_height()?.unwrap_or_default();\nlet last = requested_last.min(current);\nif first > last { return Ok(empty_range_response()); }\nlet resp = source.get_block_range(first, last)?;","handlingStrategy":"validation","validationCode":"let current = source.get_current_height()?.unwrap_or_default();\nlet last = requested_last.min(current);\nif first > last {\n    // nothing synced in range yet — wait for sync or return empty\n    return Ok(BlockRangeResponse::default());\n}\nlet resp = source.get_block_range(first, last)?;","typeGuard":"fn range_is_synced(source: &impl BlockSource, first: u32, last: u32) -> bool {\n    source.get_current_height().ok().flatten().map_or(false, |h| last <= h.into())\n}","tryCatchPattern":"match source.get_block_range(first, last) {\n    Err(e) if e.to_string().contains(\"greater than current synced height\") => {\n        // cache behind: reschedule after sync progress instead of failing the job\n        schedule_retry_after_sync();\n    }\n    other => other,\n}","preventionTips":["Always derive range bounds from the cache's own get_current_height(), never an external tip","On cold start, wait for initial sync before issuing range queries","Treat this error as a backpressure signal: retry later rather than surfacing it to users"],"tags":["rust","fuel","database","sync","block-height","cache","validation"],"backgroundTag":null,"analyzedSha":"b9d4d170da3a31c9ace5f963d633b326348e0d42","analyzedAt":"2026-08-16T08:56:42.692Z","schemaVersion":2},"datasetVersion":"2026-08-16T13:17:31.715Z"}