FuelLabs/fuels-ts · error · FuelError

ASSET_BURN_DETECTED

ASSET_BURN_DETECTED

Error message

Asset burn detected.
Add the relevant change outputs to the transaction to avoid burning assets.
Or enable asset burn, upon sending the transaction.

What it means

Thrown by validateTransactionForAssetBurn when the transaction would burn a non-base-asset input that has no matching change output, and the caller has not opted into asset burn. The SDK computes getBurnableAssetCount: coin inputs (and message inputs with amount > 0 on the base asset) whose assetId has no Change output are considered burnable. Burning is destructive, so it is opt-in via enableAssetBurn.

Source

Thrown at packages/account/src/providers/transaction-request/helpers.ts:169

  transactionRequest: TransactionRequest,
  enableAssetBurn: boolean = false
) => {
  // Asset burn is enabled
  if (enableAssetBurn === true) {
    return;
  }

  // No burnable assets detected
  if (getBurnableAssetCount(baseAssetId, transactionRequest) <= 0) {
    return;
  }

  const message = [
    'Asset burn detected.',
    'Add the relevant change outputs to the transaction to avoid burning assets.',
    'Or enable asset burn, upon sending the transaction.',
  ].join('\n');
  throw new FuelError(ErrorCode.ASSET_BURN_DETECTED, message);
};

View on GitHub (pinned to b3f37c91ac)

Solutions

  1. Add a Change output for each assetId present in the inputs: tx.addChangeOutput?(...) or ensure the account/assemble flow adds change outputs.
  2. If burning is intentional, pass enableAssetBurn: true on the send/submit path.
  3. Audit inputs vs outputs by assetId before submitting: every input assetId should have a change or matching output.
  4. Use the account's higher-level send flows (transfer/sendTransaction) which add change outputs automatically.

Example fix

// before — input asset has no change output -> would burn
const tx = new ScriptTransactionRequest();
tx.addCoinInput(coinOfAssetB);
tx.addCoinOutput(recipient, coinOfAssetB.amount, assetB); // no change output for assetB leftover

// after — add a change output for each asset (or let the SDK do it)
tx.addChangeOutput?.(); // or use account.transfer which adds change outputs

// or, if burning is intended
await provider.sendTransaction(tx, { enableAssetBurn: true });
Defensive patterns

Strategy: validation

Validate before calling

function assertNoUnintendedBurn(baseAssetId, tx) {
  const inputAssets = new Set(tx.inputs.filter(isRequestInputCoin).map(i => i.assetId));
  const changeAssets = new Set(tx.outputs.filter(o => o.type === OutputType.Change).map(o => o.assetId));
  const burnt = [...inputAssets].filter(a => !changeAssets.has(a));
  if (burnt.length) throw new Error(`Missing change output for assets: ${burnt.join(', ')}`);
}

Type guard

function hasChangeOutputForEveryAsset(tx): boolean {
  const inAssets = new Set(tx.inputs.filter(isRequestInputCoin).map(i => i.assetId));
  const outAssets = new Set(tx.outputs.filter(o => o.type === OutputType.Change).map(o => o.assetId));
  return [...inAssets].every(a => outAssets.has(a));
}

Try / catch

import { FuelError, ErrorCode } from '@fuel-ts/errors';
try {
  await provider.sendTransaction(tx);
} catch (e) {
  if (e instanceof FuelError && e.code === ErrorCode.ASSET_BURN_DETECTED) {
    // either add the missing change outputs, or pass enableAssetBurn: true if burning is intended
  }
  throw e;
}

Prevention

When it happens

Trigger: Building a transaction that spends an asset but omits the Change output for that assetId; transferring all of a coin's amount forward without a change output for the remainder; sending a tx with inputs of an asset but outputs only for a different asset; calling sendTransaction without enableAssetBurn when the assembled tx would burn.

Common situations: Manually constructing a ScriptTransactionRequest and forgetting a change output per asset; spending a message with amount > 0 on the base asset without a base-asset change output; intentionally burning but not setting enableAssetBurn; SDK upgrade that started enforcing this guard by default.

Related errors


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