FuelLabs/fuel-core · error · anyhow::Error
Off chain database is already initialized
Error message
Off chain database is already initialized
What it means
Companion to the on-chain check: the off-chain database's into_genesis() fails when it already contains indexed state. Both databases must be empty for SnapshotImporter to run; this error names the off-chain side as the initialized one.
Source
Thrown at crates/fuel-core/src/service/genesis.rs:88
/// Performs the importing of the genesis block from the snapshot.
pub async fn execute_genesis_block(
watcher: StateWatcher,
config: &Config,
db: &CombinedDatabase,
) -> anyhow::Result<UncommittedImportResult<Changes>> {
let genesis_block = create_genesis_block(config);
tracing::info!("Genesis block created: {:?}", genesis_block.header());
let on_chain = db
.on_chain()
.clone()
.into_genesis()
.map_err(|_| anyhow::anyhow!("On chain database is already initialized"))?;
let off_chain = db
.off_chain()
.clone()
.into_genesis()
.map_err(|_| anyhow::anyhow!("Off chain database is already initialized"))?;
let genesis_db = CombinedGenesisDatabase {
on_chain,
off_chain,
};
SnapshotImporter::import(
genesis_db.clone(),
genesis_block.clone(),
config.snapshot_reader.clone(),
watcher,
)
.await?;
let genesis_progress_on_chain: Vec<String> = db
.on_chain()
.iter_all_keys::<GenesisMetadata<OnChain>>(None)
.try_collect()?;View on GitHub (pinned to b9d4d170da)
Solutions
- Wipe the entire database directory (on-chain AND off-chain together) before re-running genesis.
- If state should be preserved, skip genesis import entirely.
- Check that db-path isn't shared between nodes/runs.
Defensive patterns
Strategy: validation
Validate before calling
// Same emptiness probe must cover BOTH databases — wiping only one side
// just moves the failure to the other:
async fn needs_genesis(db: &CombinedDatabase) -> bool {
on_chain_is_empty(db.on_chain()).await && off_chain_is_empty(db.off_chain()).await
} Try / catch
if let Err(e) = genesis_result {
if e.to_string().contains("already initialized") {
return Err(anyhow!("off-chain (or on-chain) DB not empty: wipe the whole db-path"));
}
return Err(e);
} Prevention
- Wipe on-chain and off-chain databases together — they must be lifecycle-aligned.
- Treat 'already initialized' as an idempotency signal: skip, don't fail, on restarts.
- Keep db-path ownership 1:1 with chains in orchestration configs.
When it happens
Trigger: execute_genesis_block runs while the off-chain DB (balances, tx-index, etc.) at the configured path already holds state from a prior run.
Common situations: Same as the on-chain case: reused data directories, partial prior initializations, CI runs sharing paths.
Related errors
- off-chain database doesn't have height
- On chain database is already initialized
- on-chain database doesn't have height
- off-chain database height({off_chain_height}) is less than t
- Database doesn't have a height to rollback
AI-assisted analysis of FuelLabs/fuel-core@b9d4d170da (2026-08-16).
Data as JSON: /api/errors/396d6eadb34f088a.
Report an issue: GitHub.