FuelLabs/fuels-ts · error · FuelError

SCRIPT_REVERTED

SCRIPT_REVERTED

Error message

Transaction reverted.

What it means

Thrown by the contract multicall script decoder when the wrapper script exits with a non-zero code, meaning one of the batched contract calls reverted on-chain. The SDK wraps multicalls in a script; a non-zero script exit signals an abort/revert inside the Sway execution of one of the calls.

Source

Thrown at packages/program/src/contract-call-script.ts:114

}

type ReturnReceipt = TransactionResultReturnReceipt | TransactionResultReturnDataReceipt;

const isReturnType = (type: ReturnReceipt['type']) =>
  type === ReceiptType.Return || type === ReceiptType.ReturnData;

const getMainCallReceipt = (
  receipts: TransactionResultCallReceipt[],
  contractId: string
): TransactionResultCallReceipt | undefined =>
  receipts.find(
    ({ type, id, to }) =>
      type === ReceiptType.Call && id === SCRIPT_WRAPPER_CONTRACT_ID && to === contractId
  );

const scriptResultDecoder = (contractId: Address) => (result: ScriptResult) => {
  if (toNumber(result.code) !== 0) {
    throw new FuelError(ErrorCode.SCRIPT_REVERTED, `Transaction reverted.`);
  }

  const mainCallResult = getMainCallReceipt(
    result.receipts as TransactionResultCallReceipt[],
    contractId.toB256()
  );
  const mainCallInstructionStart = bn(mainCallResult?.is);

  const receipts = result.receipts as ReturnReceipt[];
  return receipts
    .filter(({ type }) => isReturnType(type))
    .flatMap((receipt: ReturnReceipt) => {
      if (!mainCallInstructionStart.eq(bn(receipt.is))) {
        return [];
      }
      if (receipt.type === ReceiptType.Return) {
        return [new BigNumberCoder('u64').encode((receipt as TransactionResultReturnReceipt).val)];
      }

View on GitHub (pinned to b3f37c91ac)

Solutions

  1. Inspect the transaction receipts (especially Revert and Log receipts) for the Sway revert reason / revert code.
  2. Re-run the call with higher gas or via dryRun to see the exact failure.
  3. Verify the contract arguments and ABI match the deployed code.
  4. Reproduce with a single call to isolate which entry in a multicall reverted.

Example fix

// before
const { value } = await contract.functions.foo(args).call();
// after — dry-run and inspect receipts
const scope = contract.functions.foo(args);
const dry = await scope.dryRun();
console.log(dry.receipts); // look for ReceiptType.Revert / Log
const { value } = await scope.call();
Defensive patterns

Strategy: try-catch

Validate before calling

// dry-run first to surface the revert reason without submitting
const dryRunResult = await contract.functions.foo(args).dryRun();
const reverted = dryRunResult.receipts.some((r) => r.type === ReceiptType.Revert);
if (reverted) throw new Error('call would revert on-chain');

Type guard

const isScriptReverted = (e: unknown): boolean =>
  e instanceof FuelError && e.code === FuelError.CODES.SCRIPT_REVERTED;

Try / catch

try {
  return await contract.functions.foo(args).call();
} catch (e) {
  if (e instanceof FuelError && e.code === FuelError.CODES.SCRIPT_REVERTED) {
    // inspect tx receipts / logs for the Sway revert reason
  }
  throw e;
}

Prevention

When it happens

Trigger: Calling a contract function (especially via multicall) where the Sway code hits an `assert`/`revert`/`abort`, runs out of gas, or receives invalid arguments that fail a require.

Common situations: Contract precondition failure (e.g. insufficient allowance, wrong owner, invalid state), gas estimation too low causing mid-script revert, swapped argument order, ABI/code mismatch after redeploy.

Related errors


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