FuelLabs/fuel-core · error · anyhow::Error
The block has more than `u16::MAX` transactions, {}
Error message
The block has more than `u16::MAX` transactions, {} What it means
The off-chain worker indexes each transaction's position in a block as a u16 (the owned-transaction index layout reserves 2 bytes for tx_idx). enumerate() yields a usize, and u16::try_from fails when a block contains more than 65535 transactions. Consensus limits keep valid Fuel blocks far below this, so the error indicates a hand-crafted or malformed block rather than normal chain data.
Source
Thrown at crates/fuel-core/src/graphql_api/worker_service.rs:367
Ok(())
}
/// Associate all transactions within a block to their respective UTXO owners
fn index_tx_owners_for_block<T>(
block: &Block,
block_st_transaction: &mut T,
chain_id: &ChainId,
) -> anyhow::Result<()>
where
T: OffChainDatabaseTransaction,
{
for (tx_idx, tx) in block.transactions().iter().enumerate() {
let block_height = *block.header().height();
let inputs;
let outputs;
let tx_idx = u16::try_from(tx_idx).map_err(|e| {
anyhow::anyhow!("The block has more than `u16::MAX` transactions, {}", e)
})?;
let tx_id = tx.id(chain_id);
match tx {
Transaction::Script(tx) => {
inputs = tx.inputs().as_slice();
outputs = tx.outputs().as_slice();
}
Transaction::Create(tx) => {
inputs = tx.inputs().as_slice();
outputs = tx.outputs().as_slice();
}
Transaction::Mint(_) => continue,
Transaction::Upgrade(tx) => {
inputs = tx.inputs().as_slice();
outputs = tx.outputs().as_slice();
}
Transaction::Upload(tx) => {
inputs = tx.inputs().as_slice();View on GitHub (pinned to b9d4d170da)
Solutions
- Reject the block before processing if block.transactions().len() > u16::MAX.
- For test chains, cap transactions per block below 65535.
- If raising the real limit is required, the index key layout (2-byte tx_idx) must be widened — a coordinated storage-format change.
Example fix
// before
let tx_idx = u16::try_from(tx_idx)?;
// after
if block.transactions().len() > u16::MAX as usize {
anyhow::bail!("block exceeds maximum supported transaction count");
}
let tx_idx = u16::try_from(tx_idx)?; Defensive patterns
Strategy: validation
Validate before calling
// Reject oversized blocks before execution/indexing.
if block.transactions().len() > u16::MAX as usize {
anyhow::bail!(
"block {} has {} transactions; max supported is {}",
block.header().height(),
block.transactions().len(),
u16::MAX
);
} Type guard
fn is_indexable_block(block: &Block) -> bool {
block.transactions().len() <= u16::MAX as usize
} Try / catch
match process_block(&block, &mut tx, &chain_id) {
Ok(()) => Ok(()),
Err(e) if e.to_string().contains("u16::MAX transactions") => {
// malformed/hand-crafted block: reject it, never retry
Err(anyhow::anyhow!("rejecting malformed block: {}", e))
}
Err(e) => Err(e),
} Prevention
- Enforce a consensus/config transaction-count limit well below 65535 on custom chains.
- Treat this error as evidence of a crafted block, not of a node bug.
- Widen the 2-byte tx_idx index layout before ever raising limits in production.
When it happens
Trigger: Processing (importing/executing) a block whose transactions() iterator yields more than u16::MAX items — custom-built blocks, fuzzing, or a changed protocol limit not reflected in the index layout.
Common situations: Test/fuzz environments injecting oversized blocks; local dev chains with relaxed limits; future consensus parameter changes raising max txs per block.
Related errors
- Transaction status already exists for tx {}
- off-chain database doesn't have height
- off-chain database height({off_chain_height}) is less than t
- The `message_block_height` is higher than `commit_block_heig
- The count of leaves - messages is zero
AI-assisted analysis of FuelLabs/fuel-core@b9d4d170da (2026-08-16).
Data as JSON: /api/errors/fa9a6659c3a6d16b.
Report an issue: GitHub.