FuelLabs/fuel-core · error · anyhow::Error
Manual block production is not allowed with trigger `Open`
Error message
Manual block production is not allowed with trigger `Open`
What it means
produce_manual_blocks rejects every manual request while the node runs Trigger::Open. With Open, block production stays open for `period` seconds and the block is only finalized when the period elapses, so the manual request cannot be resolved immediately as SharedState::manually_produce_block's oneshot caller expects. The guard is an explicit config-combination check, not a runtime failure.
Source
Thrown at crates/services/consensus_module/poa/src/service.rs:337
deadline: Instant,
) -> anyhow::Result<()> {
self.produce_block(
self.next_height(),
self.next_time(RequestType::Trigger)?,
TransactionsSource::TxPool,
deadline,
)
.await
}
async fn produce_manual_blocks(
&mut self,
block_production: ManualProduction,
) -> anyhow::Result<()> {
// The caller of manual block production expects that it is resolved immediately
// while in the case of `Trigger::Open` we need to wait for the period to pass.
if matches!(self.trigger, Trigger::Open { .. }) {
return Err(anyhow!(
"Manual block production is not allowed with trigger `Open`"
))
}
let mut block_time = if let Some(time) = block_production.start_time {
time
} else {
self.next_time(RequestType::Manual)?
};
match block_production.mode {
Mode::Blocks { number_of_blocks } => {
for _ in 0..number_of_blocks {
self.produce_block(
self.next_height(),
block_time,
TransactionsSource::TxPool,
Instant::now(),
)View on GitHub (pinned to b9d4d170da)
Solutions
- Switch the node's trigger to Trigger::Interval { block_time } or Trigger::Instant in the PoA config when tests/tooling need manual production.
- Do not call manually_produce_block against Open-configured nodes; wait for the open period to close the block instead.
- Gate the call up front: check the configured Trigger before sending a Request::ManualBlocks.
Example fix
// before
let config = Config {
trigger: Trigger::Open { period: Duration::from_secs(5) },
..Default::default()
};
// ...
shared_state.manually_produce_block(None, Mode::Blocks { number_of_blocks: 1 }).await?; // Err
// after
let config = Config {
trigger: Trigger::Interval { block_time: Duration::from_secs(5) },
..Default::default()
};
// ...
shared_state.manually_produce_block(None, Mode::Blocks { number_of_blocks: 1 }).await?; // Ok Defensive patterns
Strategy: validation
Validate before calling
// Check before sending the manual request
fn manual_production_allowed(trigger: &fuel_core_poa::Trigger) -> bool {
!matches!(trigger, fuel_core_poa::Trigger::Open { .. })
}
if !manual_production_allowed(&config.trigger) {
anyhow::bail!("node uses Trigger::Open; manual block production is rejected");
}
shared_state.manually_produce_block(start_time, mode).await?; Try / catch
match shared_state.manually_produce_block(start_time, mode).await {
Err(err) if err.to_string().contains("Manual block production is not allowed") => {
// config bug: switch trigger to Interval/Instant or wait for the open period
}
other => other,
} Prevention
- In test harnesses, pick one strategy per node: Trigger::Open for period-based tests, Interval/Instant where tests force blocks manually.
- Assert the trigger variant in test setup before any manually_produce_block call.
- Treat this error as a permanent config mismatch — retrying the identical request always fails.
When it happens
Trigger: Calling SharedState::manually_produce_block(start_time, Mode::Blocks{..} | Mode::BlockWithTransactions(..)) on a node whose Config.trigger is Trigger::Open { period } (crates/services/consensus_module/poa/src/service.rs:336). Typical in integration tests that reuse an Open-configured Service and then force blocks.
Common situations: Test harnesses configured for Trigger::Open (e.g. testing pre-confirmation flows) that also call manual production helpers; config migrated from Interval to Open while old test code still forces blocks; newer fuel-core versions where Trigger::Open was introduced and tests were not updated.
Related errors
- unable to produce blocks without a consensus key
- The block timestamp should monotonically increase
- Time exceeds system limits
- The provided time parameters lead to an overflow
- Block production timed out
AI-assisted analysis of FuelLabs/fuel-core@b9d4d170da (2026-08-16).
Data as JSON: /api/errors/4d4b48696b81403b.
Report an issue: GitHub.