linera-io/linera-protocol · error · ExecutionError

MaximumFuelExceeded

MaximumFuelExceeded

Error message

ExecutionError::MaximumFuelExceeded(vm_runtime)

What it means

track_fuel accumulates Wasm fuel consumed within a block via consume_fuel; when the running total exceeds the policy's maximum_wasm_fuel_per_block, execution fails with MaximumFuelExceeded(VmRuntime::Wasm) (resources.rs:496). Every Wasm instruction executed by the block's operations and messages is metered against this per-block cap.

Source

Thrown at linera-execution/src/resources.rs:496

            .ok_or(ArithmeticError::Overflow)?;
        self.update_balance(self.policy.http_request)
    }

    /// Tracks a number of fuel units used.
    pub(crate) fn track_fuel(
        &mut self,
        fuel: u64,
        vm_runtime: VmRuntime,
    ) -> Result<(), ExecutionError> {
        match vm_runtime {
            VmRuntime::Wasm => {
                self.tracker.as_mut().wasm_fuel = self
                    .tracker
                    .as_ref()
                    .wasm_fuel
                    .checked_add(fuel)
                    .ok_or(ArithmeticError::Overflow)?;
                ensure!(
                    self.tracker.as_ref().wasm_fuel <= self.policy.maximum_wasm_fuel_per_block,
                    ExecutionError::MaximumFuelExceeded(vm_runtime)
                );
            }
            VmRuntime::Evm => {
                self.tracker.as_mut().evm_fuel = self
                    .tracker
                    .as_ref()
                    .evm_fuel
                    .checked_add(fuel)
                    .ok_or(ArithmeticError::Overflow)?;
                ensure!(
                    self.tracker.as_ref().evm_fuel <= self.policy.maximum_evm_fuel_per_block,
                    ExecutionError::MaximumFuelExceeded(vm_runtime)
                );
            }
        }
        self.update_balance(self.policy.fuel_price(fuel, vm_runtime)?)

View on GitHub (pinned to 6c226ddcb3)

Solutions

  1. Split the work across multiple blocks (fewer operations per block)
  2. Optimize the contract: remove hot loops, cache results, reduce per-operation fuel
  3. If you operate the committee, raise maximum_wasm_fuel_per_block in the resource policy

Example fix

// before: all operations in one block
block.extend(operations);
propose(block)?;

// after: split into blocks sized under the per-block fuel cap
for chunk in operations.chunks(max_ops_per_block) {
    propose(Block::new(chunk.to_vec()))?;
}
Defensive patterns

Strategy: fallback

Validate before calling

// Estimate Wasm fuel per operation (from a benchmark or previous run) and
// cap the batch before proposing the block.
fn fits_fuel_budget(ops: &[Operation], est_fuel: impl Fn(&Operation) -> u64, max: u64) -> bool {
    ops.iter().map(&est_fuel).try_fold(0u64, |acc, f| acc.checked_add(f))
        .map(|total| total <= max)
        .unwrap_or(false)
}

if !fits_fuel_budget(&ops, estimate, policy.maximum_wasm_fuel_per_block) {
    ops.truncate(smaller_batch_len); // propose a smaller block
}

Type guard

fn is_wasm_fuel_exceeded(err: &ExecutionError) -> bool {
    matches!(err, ExecutionError::MaximumFuelExceeded(VmRuntime::Wasm))
}

Try / catch

match proposer.propose(block).await {
    Ok(h) => h,
    Err(ref e) if is_wasm_fuel_exceeded(e) => {
        // fallback: split the block in half and propose sequentially
        let (a, b) = block.operations.split_at(block.operations.len() / 2);
        propose_all(vec![a.to_vec(), b.to_vec()]).await
    }
    Err(e) => return Err(e.into()),
}

Prevention

When it happens

Trigger: A block whose combined operations and messages burn more Wasm fuel than maximum_wasm_fuel_per_block: long-running loops in a contract, heavy computation, or too many operations batched into one block.

Common situations: Batching many operations into a single proposed block; compute-heavy contract upgrades; policy caps tightened by a new epoch; benchmark contracts with unbounded loops.

Related errors


AI-assisted analysis of linera-io/linera-protocol@6c226ddcb3 (2026-08-22). Data as JSON: /api/errors/d3ba4eb9ae3423ea. Report an issue: GitHub.