FuelLabs/fuel-core · error · anyhow::Error
The block production is disabled
Error message
The block production is disabled
What it means
PoAAdapter wraps Option<SharedState>; the PoA service (and its shared state) is only constructed when block production is enabled (sub_services.rs:423-448: `production_enabled.then(...)`). With shared_state == None, manually_produce_blocks refuses immediately — manual production requires a running producer loop to interact with.
Source
Thrown at crates/fuel-core/src/service/adapters/consensus_module/poa.rs:1241
/// A block at this height already exists in the stream.
HeightExists,
/// Lock lost or epoch is stale — another leader holds the lock.
FencingRejected,
}
impl PoAAdapter {
pub fn new(shared_state: Option<SharedState>) -> Self {
Self { shared_state }
}
pub async fn manually_produce_blocks(
&self,
start_time: Option<Tai64>,
mode: Mode,
) -> anyhow::Result<()> {
self.shared_state
.as_ref()
.ok_or(anyhow!("The block production is disabled"))?
.manually_produce_block(start_time, mode)
.await
}
}
#[async_trait::async_trait]
impl BlockReconciliationReadPort for NoopReconciliationAdapter {
async fn leader_state(
&self,
_next_height: BlockHeight,
) -> anyhow::Result<LeaderState> {
Ok(LeaderState::ReconciledLeader)
}
async fn release(&self) -> anyhow::Result<()> {
Ok(())
}
}View on GitHub (pinned to b9d4d170da)
Solutions
- Start the node with block production enabled (dev/production consensus config) so SharedState exists.
- Only invoke manual production on nodes actually configured as producers.
- In tests/harnesses, construct the adapter with PoAAdapter::new(Some(shared_state)).
Example fix
// before let adapter = PoAAdapter::new(None); // production disabled adapter.manually_produce_blocks(None, mode).await?; // always errors // after — enable production so the PoA service (and SharedState) is built // (node config: enable block production), then: let adapter = PoAAdapter::new(Some(shared_state)); adapter.manually_produce_blocks(None, mode).await?;
Defensive patterns
Strategy: validation
Validate before calling
// Before calling manually_produce_blocks, confirm the node actually runs
// block production (PoA service was constructed) — e.g. reflect your config:
fn block_production_enabled(cfg: &Config) -> bool {
cfg.consensus_key_config.is_some() /* or your production flag */
}
if !block_production_enabled(&config) {
anyhow::bail!("refusing manual production: node is not a producer");
} Try / catch
// If surfaced via an API layer, map to a clear client error:
if let Err(e) = result {
if e.to_string().contains("block production is disabled") {
return Err(anyhow!("this node is not configured for block production"));
}
return Err(e);
} Prevention
- Only expose manual-production endpoints on producer-configured nodes.
- Fail fast at startup if your tooling requires production but config disables it.
- Keep dev tooling and production flags in sync in node configuration.
When it happens
Trigger: Calling manually_produce_blocks (e.g. a dev/GraphQL block-production trigger) on a node whose PoA service was never created because block production is disabled in its configuration.
Common situations: Running a plain non-producing node (regular validator/follower) and trying to trigger manual production; disabling production in config while keeping dev tooling enabled; test harnesses constructing PoAAdapter::new(None).
Related errors
- Block production timed out
- Manual block production is not allowed with trigger `Open`
- unable to produce blocks without a consensus key
- Time exceeds system limits
- The provided time parameters lead to an overflow
AI-assisted analysis of FuelLabs/fuel-core@b9d4d170da (2026-08-16).
Data as JSON: /api/errors/0b5c56238f5e8fe7.
Report an issue: GitHub.