FuelLabs/fuels-ts · error · FuelError

INSUFFICIENT_FUNDS

INSUFFICIENT_FUNDS

Error message

Insufficient funds to consolidate.
	Asset ID: ${baseAssetId}
	Owner: ${account.address.toB256()}

What it means

Thrown by consolidateCoins() when, after fetching and sorting all base-asset coins for the account, the 'funding' array is empty. With no funding coins, the account cannot pay gas for even the first consolidation transaction. The message echoes the base asset id and owner address for diagnosis.

Source

Thrown at packages/account/src/utils/consolidate-coins.ts:145

  let funding: Coin[] = [];
  let dust: Coin[] = [];

  // We get the largest coin/s for funding purposes
  if (isBaseAsset) {
    const coins = await getAllCoins(account, baseAssetId).then(sortCoins);
    funding = coins.slice(0, numberOfFundingCoins);
    dust = coins.slice(numberOfFundingCoins);
  } else {
    funding = await getAllCoins(account, baseAssetId)
      .then(sortCoins)
      .then((coins) => coins.slice(0, numberOfFundingCoins));
    dust = await getAllCoins(account, assetId).then(({ coins }) => coins);
  }

  // There a better way of detecting whether the account has enough funds to consolidate
  if (funding.length === 0) {
    throw new FuelError(
      ErrorCode.INSUFFICIENT_FUNDS,
      `Insufficient funds to consolidate.\n\tAsset ID: ${baseAssetId}\n\tOwner: ${account.address.toB256()}`
    );
  }

  const batches = [
    ...splitEvery(batchSize, funding),
    // We leave one coin for the funding coin
    ...splitEvery(batchSize - 1, dust),
  ];

  const txs: ScriptTransactionRequest[] = batches.map((batch) => {
    const request = new ScriptTransactionRequest({
      scriptData: '0x',
    });

    // Add our dust coins as inputs
    request.addResources(batch);

View on GitHub (pinned to b3f37c91ac)

Solutions

  1. Fund the account with base-asset coins (e.g. via a faucet or transfer) before consolidating.
  2. Verify account.address matches the account that owns the coins you expect.
  3. Confirm provider.getBaseAssetId() returns the asset id the account is funded with.
  4. If consolidating a non-base asset, the account still needs base-asset coins to pay gas.

Example fix

// before
await account.consolidateCoins({ assetId }); // account has no base asset
// after
await faucet.fund(account.address, baseAssetId, 1_000_000);
await account.consolidateCoins({ assetId });
Defensive patterns

Strategy: validation

Validate before calling

const baseCoins = await account.getCoins(baseAssetId);
if (baseCoins.coins.length === 0) {
  throw new Error('Account has no base-asset coins; fund it before consolidating.');
}

Try / catch

try {
  await account.consolidateCoins({ assetId });
} catch (err) {
  if (err instanceof FuelError && err.code === ErrorCode.INSUFFICIENT_FUNDS) {
    await faucet.fund(account.address, baseAssetId, minBalance);
    await account.consolidateCoins({ assetId });
  } else throw err;
}

Prevention

When it happens

Trigger: Calling account.consolidateCoins / startConsolidation on an account that holds zero coins of the base asset (the fee-paying asset), regardless of whether it holds other assets. The check is funding.length === 0 after getAllCoins(account, baseAssetId).

Common situations: Fresh account never funded with base asset; account drained by prior transactions; wrong account selected for consolidation; baseAssetId mismatch between provider config and the asset the account actually holds; test that funds only non-base assets.

Related errors


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