FuelLabs/fuels-ts · error · FuelError

GAS_LIMIT_TOO_LOW

GAS_LIMIT_TOO_LOW

Error message

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

What it means

Thrown while finalizing a funded transaction when an explicit gas limit was supplied (via txParameters.gasLimit or callParams.gasLimit) but it is below the gas the SDK actually estimated as required (gasUsed). The SDK will not silently raise your cap; it treats an under-set gas limit as a caller error. When no gas limit is specified, the SDK simply sets transactionRequest.gasLimit = gasUsed.

Source

Thrown at packages/program/src/functions/base-invocation-scope.ts:666

  }

  /**
   * In case the gasLimit is *not* set by the user, this method sets a default value.
   */
  private setDefaultTxParams(
    transactionRequest: ScriptTransactionRequest,
    gasUsed: BN,
    maxFee: BN
  ) {
    const gasLimitSpecified = isDefined(this.txParameters?.gasLimit) || this.hasCallParamsGasLimit;
    const maxFeeSpecified = isDefined(this.txParameters?.maxFee);

    const { gasLimit: setGasLimit, maxFee: setMaxFee } = transactionRequest;

    if (!gasLimitSpecified) {
      transactionRequest.gasLimit = gasUsed;
    } else if (setGasLimit.lt(gasUsed)) {
      throw new FuelError(
        ErrorCode.GAS_LIMIT_TOO_LOW,
        `Gas limit '${setGasLimit}' is lower than the required: '${gasUsed}'.`
      );
    }

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

View on GitHub (pinned to b3f37c91ac)

Solutions

  1. Omit gasLimit entirely and let the SDK estimate it from gasUsed.
  2. Estimate first (await scope.txParams({}).getTransactionRequest() / dryRun) and set gasLimit to a value >= gasUsed (add a margin).
  3. Raise the explicit gasLimit to at least the value reported in the error message.

Example fix

// before
await contract.functions.heavy().tx({ gasLimit: 1000 }).call();

// after — let the SDK estimate
await contract.functions.heavy().call();
// or set an adequate limit
await contract.functions.heavy().tx({ gasLimit: 1_000_000 }).call();
Defensive patterns

Strategy: validation

Validate before calling

// Omit gasLimit unless you have a confident estimate >= gasUsed.
// Optionally estimate first:
const prepared = await contract.functions.fn().txParams({}).getTransactionRequest();
// `prepared` exposes computed gas; set gasLimit only if it exceeds that.

Try / catch

try {
  await contract.functions.fn().tx({ gasLimit }).call();
} catch (e) {
  if (e instanceof FuelError && e.code === ErrorCode.GAS_LIMIT_TOO_LOW) {
    // retry without an explicit gasLimit to let the SDK estimate
    await contract.functions.fn().call();
  } else throw e;
}

Prevention

When it happens

Trigger: Calling .tx({ gasLimit: N }) or .callParams({ gasLimit: N }) with N smaller than the estimated gas; computing gasLimit from stale constants; reusing a gasLimit tuned for a cheaper function on a heavier one.

Common situations: Hard-coding a gasLimit from an older contract build after adding logic that needs more gas; setting gasLimit to a 'safe-looking' small number; mixing gasLimit on both .tx() and .callParams() and under-shooting.

Related errors


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