FuelLabs/fuels-ts · error · FuelError

GAS_LIMIT_TOO_LOW

GAS_LIMIT_TOO_LOW

Error message

Gas limit '${setGasLimit}' is lower than the required: '${requiredGasLimit}'.

What it means

Thrown by setAndValidateGasAndFeeForAssembledTx when a caller-supplied setGasLimit (for a Script transaction) is less than the gas the node estimates is required to execute the script (transactionRequest.gasLimit at that point). The guard prevents submitting a script that will run out of gas on-chain. It only applies to Script-type requests (create/upgrade txs are exempt).

Source

Thrown at packages/account/src/providers/assemble-tx-helpers.ts:72

};

export const setAndValidateGasAndFeeForAssembledTx = async <T extends TransactionRequest>(params: {
  transactionRequest: T;
  provider: Provider;
  gasPrice: BN;
  setGasLimit?: BigNumberish;
  setMaxFee?: BigNumberish;
}): Promise<T> => {
  const { gasPrice, transactionRequest, setGasLimit, setMaxFee, provider } = params;

  const gasLimitSpecified = isDefined(setGasLimit);
  const maxFeeSpecified = isDefined(setMaxFee);
  const isScriptTx = transactionRequest.type === TransactionType.Script;

  if (gasLimitSpecified && isScriptTx) {
    const requiredGasLimit = transactionRequest.gasLimit;
    if (bn(setGasLimit).lt(bn(requiredGasLimit))) {
      throw new FuelError(
        ErrorCode.GAS_LIMIT_TOO_LOW,
        `Gas limit '${setGasLimit}' is lower than the required: '${requiredGasLimit}'.`
      );
    }

    transactionRequest.gasLimit = bn(setGasLimit);
  }

  if (maxFeeSpecified) {
    const requiredMaxFee = transactionRequest.maxFee;
    if (bn(setMaxFee).lt(requiredMaxFee)) {
      throw new FuelError(
        ErrorCode.MAX_FEE_TOO_LOW,
        `Max fee '${setMaxFee}' is lower than the required: '${requiredMaxFee}'.`
      );
    }

    transactionRequest.maxFee = bn(setMaxFee);

View on GitHub (pinned to b3f37c91ac)

Solutions

  1. Omit setGasLimit to let the SDK estimate and set the required gas automatically.
  2. If you must set it, first read transactionRequest.gasLimit (after estimation) and pass a value >= it.
  3. Re-estimate via provider.estimateTxGas before specifying setGasLimit.
  4. Add a safety margin: setGasLimit = bn(estimatedGasLimit).mul(12).div(10).

Example fix

// before
const res = await account.assembleTx({ transactionRequest, setGasLimit: 100 });

// after — let the SDK estimate, or pass a value >= required
const { gasUsed } = await provider.estimateTxGas(transactionRequest);
const res = await account.assembleTx({
  transactionRequest,
  setGasLimit: bn(gasUsed).mul(12).div(10), // >= required
});
Defensive patterns

Strategy: validation

Validate before calling

import { bn } from '@fuel-ts/math';
function validateGasLimit(setGasLimit, requiredGasLimit) {
  if (bn(setGasLimit).lt(bn(requiredGasLimit))) {
    throw new Error(`Gas limit must be >= ${requiredGasLimit.toString()}`);
  }
}

Type guard

function gasLimitIsSufficient(setGasLimit, requiredGasLimit): boolean {
  return bn(setGasLimit).gte(bn(requiredGasLimit));
}

Try / catch

import { FuelError, ErrorCode } from '@fuel-ts/errors';
try {
  await account.assembleTx({ transactionRequest, setGasLimit });
} catch (e) {
  if (e instanceof FuelError && e.code === ErrorCode.GAS_LIMIT_TOO_LOW) {
    // drop setGasLimit to let the SDK estimate, or bump it
  }
  throw e;
}

Prevention

When it happens

Trigger: Calling an assemble/send flow with setGasLimit set to a value below the estimated required gas for a Script transaction; passing a hardcoded low gas limit; computing gas conservatively before estimation updated the request.

Common situations: Migrating from an SDK version that did not validate gas; copying a gas value from a testnet that underestimates mainnet script complexity; setting gas based on the script body without accounting for data inputs; pre-setting gas to avoid overpay but going below the floor.

Related errors


AI-assisted analysis of FuelLabs/fuels-ts@b3f37c91ac (2026-08-12). Data as JSON: /api/errors/ebd1c3c914d82162. Report an issue: GitHub.