{"record":{"id":"8ba95223c7bcffbe","repo":"FuelLabs/fuel-core","slug":"off-chain-database-height-off-chain-height-is-l","errorCode":null,"errorMessage":"off-chain database height({off_chain_height}) is less than target height({target_block_height})","messagePattern":"off-chain database height\\((.+?)\\) is less than target height\\((.+?)\\)","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/fuel-core/src/combined_database.rs","lineNumber":531,"sourceCode":"            {\n                if on_chain_height == target_block_height\n                    && off_chain_height == target_block_height\n                    && gas_price_rolled_back\n                    && compression_db_rolled_back\n                {\n                    break;\n                }\n            }\n\n            if on_chain_height < target_block_height {\n                return Err(anyhow::anyhow!(\n                    \"on-chain database height({on_chain_height}) \\\n                    is less than target height({target_block_height})\"\n                ));\n            }\n\n            if off_chain_height < target_block_height {\n                return Err(anyhow::anyhow!(\n                    \"off-chain database height({off_chain_height}) \\\n                    is less than target height({target_block_height})\"\n                ));\n            }\n\n            if let Some(gas_price_chain_height) = gas_price_chain_height\n                && gas_price_chain_height < target_block_height\n            {\n                return Err(anyhow::anyhow!(\n                    \"gas-price database height({gas_price_chain_height}) \\\n                    is less than target height({target_block_height})\"\n                ));\n            }\n\n            if let Some(compression_db_height) = compression_db_height\n                && compression_db_height < target_block_height\n            {\n                return Err(anyhow::anyhow!(","sourceCodeStart":513,"sourceCodeEnd":549,"githubUrl":"https://github.com/FuelLabs/fuel-core/blob/b9d4d170da3a31c9ace5f963d633b326348e0d42/crates/fuel-core/src/combined_database.rs#L513-L549","documentation":"The off-chain counterpart of the on-chain height guard in rollback_to: the off-chain database's latest height is strictly below target_block_height, so it cannot be rolled back to the target. The off-chain DB never indexed blocks up to the requested height, indicating divergence between caller expectation and off-chain state.","triggerScenarios":"rollback_to with a target above the off-chain database's indexed height — typical when the off-chain DB lags behind the on-chain DB (crash during indexing) or was rebuilt/reset while the target was computed from the on-chain chain.","commonSituations":"Off-chain worker fell behind or its DB was reset; snapshot restore mixing on-chain and off-chain from different heights; passing a target derived from chain state without checking off-chain progress.","solutions":["Let the off-chain worker catch up to the on-chain height, then retry the rollback.","If the off-chain DB is stale/corrupt, delete it and let the node rebuild indexes from on-chain data before rolling back.","Always compute the rollback target from the minimum of the component databases' current heights."],"exampleFix":null,"handlingStrategy":"validation","validationCode":"let off_chain = combined_db\n    .off_chain()\n    .latest_height_from_metadata()?\n    .ok_or_else(|| anyhow::anyhow!(\"off-chain DB empty\"))?;\nif target_block_height > off_chain {\n    anyhow::bail!(\"target {} above off-chain height {}; let the worker catch up\", target_block_height, off_chain);\n}","typeGuard":null,"tryCatchPattern":"match combined_db.rollback_to(target, &mut shutdown) {\n    Ok(()) => Ok(()),\n    Err(e) if e.to_string().contains(\"off-chain database height\") => {\n        // off-chain DB lagging: rebuild or let it catch up, then retry\n        wait_for_off_chain_catchup().await?;\n        combined_db.rollback_to(target, &mut shutdown)\n    }\n    Err(e) => Err(e),\n}","preventionTips":["Monitor off-chain worker height vs on-chain height and alert on lag.","The off-chain DB is rebuildable: when in doubt, rebuild instead of rolling back a lagging DB.","Derive targets from min(on_chain, off_chain) heights."],"tags":["database","rollback","off-chain","height-mismatch","rust"],"backgroundTag":null,"analyzedSha":"b9d4d170da3a31c9ace5f963d633b326348e0d42","analyzedAt":"2026-08-16T08:56:42.692Z","schemaVersion":2},"datasetVersion":"2026-08-16T13:17:31.715Z"}