FuelLabs/fuels-ts · warning · FuelError

NO_COINS_TO_CONSOLIDATE

NO_COINS_TO_CONSOLIDATE

Error message

No coins to consolidate.

What it means

Thrown by validateConsolidationTxsCoins when the supplied coin array has 0 or 1 entries. Consolidation merges many UTXOs into fewer ones; with a single coin there is nothing to consolidate, so the SDK aborts rather than build a no-op transaction that still costs gas. Called from assembleBaseAssetConsolidationTxs and assembleNonBaseAssetConsolidationTxs.

Source

Thrown at packages/account/src/account.ts:1275

      return await assembleTx();
    }
  }

  /** @hidden * */
  private validateTransferAmount(amount: BigNumberish) {
    if (bn(amount).lte(0)) {
      throw new FuelError(
        ErrorCode.INVALID_TRANSFER_AMOUNT,
        'Transfer amount must be a positive number.'
      );
    }
  }

  /** @hidden * */
  private validateConsolidationTxsCoins(coins: Coin[], assetId: string) {
    if (coins.length <= 1) {
      throw new FuelError(ErrorCode.NO_COINS_TO_CONSOLIDATE, 'No coins to consolidate.');
    }

    if (!coins.every((c) => c.assetId === assetId)) {
      throw new FuelError(
        ErrorCode.COINS_ASSET_ID_MISMATCH,
        'All coins to consolidate must be from the same asset id.'
      );
    }
  }

  /** @hidden * */
  private async setTransactionStateForConnectors(params: {
    transactionRequest: TransactionRequest;
    connectorOptions: AccountSendTxParams;
  }): Promise<{
    transactionRequest: TransactionRequest;
    connectorsSendTxParams: FuelConnectorSendTxParams;
  }> {

View on GitHub (pinned to b3f37c91ac)

Solutions

  1. Check the UTXO count for the asset before consolidating and skip if <= 1: const coins = await provider.getCoins(account, assetId); if (coins.length > 1) await account.consolidateCoins({ assetId });.
  2. Wrap the call in a try/catch for NO_COINS_TO_CONSOLIDATE and treat it as an expected no-op.
  3. Re-fetch coins right before consolidation rather than trusting a stale count.

Example fix

// before
await account.consolidateCoins({ assetId });

// after
const { coins } = await provider.getCoins(account.address, assetId);
if (coins.length > 1) {
  await account.consolidateCoins({ assetId });
}
Defensive patterns

Strategy: validation

Validate before calling

// Only consolidate when there is more than one UTXO
const { coins } = await provider.getCoins(account.address, assetId);
if (coins.length > 1) {
  await account.consolidateCoins({ assetId });
}

Type guard

function hasMultipleCoins(coins: Coin[]): boolean {
  return coins.length > 1;
}

Try / catch

try {
  await account.consolidateCoins({ assetId });
} catch (e) {
  if (e instanceof FuelError && e.code === ErrorCode.NO_COINS_TO_CONSOLIDATE) {
    // expected no-op; nothing to consolidate
  } else throw e;
}

Prevention

When it happens

Trigger: Calling account.consolidateCoins({ assetId }) (or the assemble*ConsolidationTxs methods) when the account has only one UTXO (or none) for that asset, or passing a pre-fetched coins array of length <= 1.

Common situations: Consolidating on a fresh or recently-swept wallet that has one UTXO left, calling consolidate repeatedly until only one UTXO remains, or filtering coins down to a single element before consolidation.

Related errors


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