FuelLabs/fuel-core · error · anyhow::Error

On chain database is already initialized

Error message

On chain database is already initialized

What it means

execute_genesis_block converts the on-chain database into a fresh 'genesis' (empty) view via into_genesis(); that conversion fails if the database already contains a genesis/chain state. Genesis import is only valid on a truly empty on-chain DB — running it against initialized storage is refused.

Source

Thrown at crates/fuel-core/src/service/genesis.rs:83

mod exporter;
mod importer;
mod progress;
mod task_manager;

/// 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?;

View on GitHub (pinned to b9d4d170da)

Solutions

  1. If re-genesis is intended: stop the node and wipe the database (delete the db directory / use the node's wipe-db option).
  2. If the DB should be kept: don't run genesis import — the chain is already initialized; start from the existing state.
  3. Ensure only one of {fresh genesis, existing chain} is attempted per db-path.
Defensive patterns

Strategy: validation

Validate before calling

// Before executing genesis import, check whether the chain DB already has
// state (e.g. a genesis block / chain height record):
async fn needs_genesis(db: &CombinedDatabase) -> bool {
    db.on_chain()
        .latest_height() // or equivalent 'is empty' probe for your version
        .is_err() // no state yet
}
if !needs_genesis(&db).await {
    tracing::info!("chain already initialized; skipping genesis import");
}

Try / catch

if let Err(e) = genesis_result {
    if e.to_string().contains("already initialized") {
        // decide explicitly: wipe and re-genesis, or continue from state
        return Err(anyhow!("DB not empty: wipe db-path or skip genesis import"));
    }
    return Err(e);
}

Prevention

When it happens

Trigger: Node startup (or an explicit genesis import) runs execute_genesis_block while the DB at the configured path already has state — e.g. restarting against the same db-path after a previous partial run.

Common situations: Reusing a data directory across node restarts with a workflow that always runs genesis import; CI reusing db paths; changing genesis config while keeping the old database.

Related errors


AI-assisted analysis of FuelLabs/fuel-core@b9d4d170da (2026-08-16). Data as JSON: /api/errors/aa6db741990755d4. Report an issue: GitHub.