FuelLabs/fuels-ts · error · FuelError

TRANSACTION_FAILED

TRANSACTION_FAILED

Error message

Failed to deploy contract chunk

What it means

Thrown inside the waitForResult() closure of ContractFactory.deployAsBlobTx() (packages/contract/src/contract-factory.ts:362) when account.sendTransaction(fundedBlobRequest) or blobTx.waitForResult() throws an error whose message does not contain the substring 'BlobId is already taken'. The code intentionally swallows the 'already taken' error (duplicate blob IDs are valid for the loader contract), but any other exception — network failure, RPC error, invalid transaction, insufficient gas — is re-thrown as TRANSACTION_FAILED.

Source

Thrown at packages/contract/src/contract-factory.ts:362

      // Deploy the chunks as blob txs
      for (const { blobId, transactionRequest } of chunks) {
        if (!uploadedBlobs.includes(blobId) && blobIdsToUpload.includes(blobId)) {
          const fundedBlobRequest = await this.assembleTx(transactionRequest, deployOptions);

          let result: TransactionResult<TransactionType.Blob>;

          try {
            const blobTx = await account.sendTransaction(fundedBlobRequest);
            result = await blobTx.waitForResult();
          } catch (err: unknown) {
            // Core will throw for blobs that have already been uploaded, but the blobId
            // is still valid so we can use this for the loader contract
            if ((<Error>err).message.indexOf(`BlobId is already taken ${blobId}`) > -1) {
              uploadedBlobs.push(blobId);
              continue;
            }

            throw new FuelError(ErrorCode.TRANSACTION_FAILED, 'Failed to deploy contract chunk');
          }

          if (!result.status || result.status !== TransactionStatus.success) {
            throw new FuelError(ErrorCode.TRANSACTION_FAILED, 'Failed to deploy contract chunk');
          }

          uploadedBlobs.push(blobId);
        }
      }

      await this.assembleTx(createRequest, deployOptions);
      txIdResolver(createRequest.getTransactionId(await account.provider.getChainId()));
      const transactionResponse = await account.sendTransaction(createRequest);
      const transactionResult = await transactionResponse.waitForResult<TransactionType.Create>();
      const contract = new Contract(contractId, this.interface, account) as T;

      return { contract, transactionResult };
    };

View on GitHub (pinned to b3f37c91ac)

Solutions

  1. Inspect the original error before it was wrapped — the FuelError message is generic, so enable SDK logging or wrap the call to capture the inner exception.
  2. Retry the deployment; transient network errors often resolve on retry.
  3. Ensure the RPC node is healthy and synced before deploying.
  4. If deploying concurrently from the same account, serialize deployments to avoid nonce conflicts.

Example fix

// before
const { waitForResult } = await factory.deployAsBlobTx();
await waitForResult();

// after
const { waitForResult } = await factory.deployAsBlobTx();
try {
  await waitForResult();
} catch (e) {
  console.error('Blob chunk deploy failed:', e);
  throw e;
}
Defensive patterns

Strategy: try-catch

Validate before calling

import { getContractChunks } from '@fuel-ts/contract';

// Before deploying, verify the RPC is reachable
try {
  await account.provider.getChain();
} catch {
  throw new Error('RPC node is not reachable; fix connectivity before deploying');
}
await factory.deployAsBlobTx();

Try / catch

const { waitForResult } = await factory.deployAsBlobTx();
try {
  await waitForResult();
} catch (e) {
  if (e instanceof FuelError && e.code === 'transaction-failed') {
    // Generic; inspect logs for the original blob-tx error
    console.error('Blob chunk submission failed. Check RPC connectivity and retry.');
    await retryWithBackoff(() => factory.deployAsBlobTx());
  } else {
    throw e;
  }
}

Prevention

When it happens

Trigger: During blob-tx deployment, a blob chunk submission fails for a reason other than the blob already existing on-chain: RPC node unreachable, transaction rejected by the node, gas estimation mismatch, account nonce conflict, or network timeout.

Common situations: Unstable RPC connection during multi-chunk deployment; gas price changes between estimation and submission; concurrent deployments from the same account causing nonce collisions; node syncing or capacity issues.

Related errors


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