FuelLabs/fuel-core · error
The override height is zero. The override height should be…
Error message
The override height is zero. The override height should be greater than zero.
What it means
Thrown at node startup by make_database_compatible_with_config (crates/fuel-core/src/service.rs:335). For ConsensusConfig::PoAV2 the node iterates poa.get_all_overrides(); when the stored block's PoA seal at an override height fails verify_consensus against the startup config, it plans a rollback to override_height - 1 via BlockHeight::pred(). An override at height 0 makes pred() return None, and since there is no height before genesis to roll back to, startup aborts with this error.
Solutions
- Move the PoAV2 override to a height greater than 0 (e.g., 1) so rollback to height-1 exists
- Wipe/regenerate the on-chain database so genesis is re-executed under the new consensus instead of rolled back
- If the goal was only new genesis keys, re-execute genesis with the new chain config rather than declaring an override at height 0
- Add a config lint that rejects override keys equal to 0 before startup
Example fix
// before (chain config consensus.PoAV2):
// overrides: { "0": { "signing_keys": [new_keys] } }
// after:
// overrides: { "1": { "signing_keys": [new_keys] } }
// (or start with a fresh database so the new keys apply at genesis) Defensive patterns
Strategy: validation
Validate before calling
fn overrides_rollbackable(poa: &PoAConfig) -> anyhow::Result<()> {
for h in poa.get_all_overrides().keys() {
anyhow::ensure!(!h.is_zero(),
"override at height 0 cannot be rolled back; use height >= 1");
}
Ok(())
}
// run before node start, before make_database_compatible_with_config Try / catch
match NodeProvider::start(&config).await {
Err(e) if e.to_string().contains("The override height is zero") => {
// config/DB mismatch at genesis: fix overrides or wipe DB, do not retry
eprintln!("override at height 0 is unsupported; move it above 0 or re-init the DB");
return Err(e);
}
other => other,
} Prevention
- Never place a PoAV2 override at height 0; the first overridable height is 1
- Treat 'change genesis consensus on an existing DB' as a re-genesis operation: wipe or migrate the database deliberately
- Lint chain configs in CI: reject override keys < 1
When it happens
Trigger: A PoAV2 chain config whose overrides map contains key height 0 (or BlockHeight::default()), used against a non-empty on-chain database whose genesis-block PoA seal no longer verifies under the new consensus config (e.g., changed/re-ordered signing keys).
Common situations: Editing PoAV2 signing-key overrides to take effect 'from genesis' while reusing an existing database; writing the first override height as 0 in a custom chain config; rotating compromised consensus keys without re-initializing the DB.
Related errors
- The consensus at override height
- The genesis block height is not found in the database…
- At least one redis url is required for leader lock
- Block not found at height
- Block production timed out
AI-assisted analysis of FuelLabs/fuel-core@b9d4d170da (2026-08-16).
Data as JSON: /api/errors/6f968f5d247260ae.
Report an issue: GitHub.
Appendix: source
Thrown at crates/fuel-core/src/service.rs:335
start_up_consensus_config,
&header,
&poa_seal,
);
if !block_valid {
found_override_height = Some(override_height);
}
} else {
return Err(anyhow::anyhow!(
"The consensus at override height {override_height} is not PoA."
));
};
}
}
}
if let Some(override_height) = found_override_height {
let rollback_height = override_height.pred().ok_or(anyhow::anyhow!(
"The override height is zero. \
The override height should be greater than zero."
))?;
tracing::warn!(
"The consensus at override height {override_height} \
does not match with the database. \
Rollbacking the database to the height {rollback_height}"
);
combined_database.rollback_to(rollback_height, shutdown_listener)?;
}
Ok(())
}
fn override_chain_config_if_needed(&self) -> anyhow::Result<()> {
let chain_config = self.shared.config.snapshot_reader.chain_config();
let on_chain_view = self.shared.database.on_chain().latest_view()?;
let chain_config_hash = chain_config.root()?.into();View on GitHub (pinned to b9d4d170da)