FuelLabs/fuel-core · error

dry run count overflow

Error message

dry run count overflow

What it means

dry_run_count tracks how many dry-runs the script gas limit estimation loop performed; it is incremented with checked_add and errors on usize overflow. Like the predicates counter, this is a defensive arithmetic guard — the dry_run_limit check earlier in the same loop bounds the count long before overflow.

Solutions

  1. Treat as an internal invariant failure and report upstream with reproduction details
  2. If you forked the node, keep the assemble_tx_dry_run_limit check intact
Defensive patterns

Strategy: try-catch

Try / catch

catch (e) { if (/dry run count overflow/.test(e.message)) { /* internal invariant: report upstream */ } else throw e; }

Prevention

When it happens

Trigger: usize overflow of the dry-run counter inside one assemble call; unreachable through the GraphQL API because dry_run_count is compared against dry_run_limit each iteration.

Common situations: Custom forks that removed the dry_run_limit check; otherwise not observable.

Related errors


AI-assisted analysis of FuelLabs/fuel-core@b9d4d170da (2026-08-16). Data as JSON: /api/errors/25f594d260f754e8. Report an issue: GitHub.

Appendix: source

Thrown at crates/fuel-core/src/schema/tx/assemble_tx.rs:817

            if !has_spendable_input {
                script.inputs_mut().push(fake_input());
            }

            // We want to calculate `max_gas` for the script, but without script limit
            *script.script_gas_limit_mut() = 0;

            let gas_used_by_tx = script.max_gas(gas_costs, fee_params);

            let max_gas_limit = max_tx_gas.saturating_sub(gas_used_by_tx);

            *script.script_gas_limit_mut() = max_gas_limit;

            let (updated_tx, new_status) = self.arguments.dry_run(script).await?;

            self.dry_run_count = self
                .dry_run_count
                .checked_add(1)
                .ok_or_else(|| anyhow::anyhow!("dry run count overflow"))?;

            let Transaction::Script(updated_script) = updated_tx else {
                return Err(anyhow::anyhow!(
                    "During script gas limit estimation, \
                        dry-run returned incorrect transaction"
                ));
            };

            script = updated_script;
            status = new_status;

            if !has_spendable_input {
                script.inputs_mut().pop();
            }

            let mut contracts_not_in_inputs = Vec::new();

            match &status.result {

View on GitHub (pinned to b9d4d170da)