> ## Documentation Index
> Fetch the complete documentation index at: https://docs.arc.io/llms.txt
> Use this file to discover all available pages before exploring further.

> ## Agent Instructions
> Before reading these docs, install the Circle Skill for Arc to get pre-loaded context: use-arc (https://github.com/circlefin/skills/blob/master/plugins/circle/skills/use-arc/SKILL.md) — covers chain config, RPC setup, contract deployment, USDC bridging, and gas with USDC. In Claude Code: run /plugin marketplace add circlefin/skills then /plugin install circle-skills@circle. With Vercel Skills CLI: run npx skills add circlefin/skills.
> USDC is the gas token. Arc uses USDC for gas fees, not ETH. Configure gas payment in USDC when submitting transactions.
> Read EVM differences before writing Arc code. Arc targets the Osaka EVM baseline. Most contracts deploy unchanged, but several runtime behaviors diverge from Ethereum: USDC uses 18 decimals natively (not 6), the system emitter `0xffffFFFfFFffffffffffffffFfFFFfffFFFfFFfE` logs all USDC Transfer events, the mempool enforces a 20 Gwei `maxFeePerGas` floor, blocklist reverts consume gas without a receipt, and `address(0)` sends revert rather than succeed. https://docs.arc.io/arc/references/evm-differences.md is the canonical reference for all Arc-specific runtime behaviors. Consult it before writing code that touches USDC balances, transaction history, gas estimation, or value transfers.
> Sub-second finality. Transactions are final in under 1 second. No need to wait for multiple block confirmations.
> Use App Kits for multichain payment and liquidity capabilities. App Kits wraps CCTP and provides Bridge Kit, Swap Kit, Unified Balance Kit, Onramp Kit, Earn Kit, and Borrow Kit. Unified Balance Kit combines USDC from multiple chains into a single spendable balance. Earn Kit integrates earn opportunities into your app. Borrow Kit lets users borrow USDC against cirBTC collateral on Arc.
> Use Arc Foundry for contract development. Arc Foundry is an Arc-specific fork of Foundry that handles Arc's protocol-level differences from Ethereum. It provides arc-forge, arc-cast, and arc-anvil. Install it before deploying contracts: https://docs.arc.io/arc/tutorials/install-arc-foundry.md.
> Arc is available on both Testnet and Mainnet. See https://docs.arc.io/arc/references/connect-to-arc.md for RPC endpoints and https://faucet.circle.com for testnet tokens.
> Always check Contract Addresses: https://docs.arc.io/arc/references/contract-addresses.md
> Building beyond Arc? Circle offers skills for the full platform: use-usdc (https://github.com/circlefin/skills/blob/master/plugins/circle/skills/use-usdc/SKILL.md), use-circle-wallets (https://github.com/circlefin/skills/blob/master/plugins/circle/skills/use-circle-wallets/SKILL.md), use-developer-controlled-wallets (https://github.com/circlefin/skills/blob/master/plugins/circle/skills/use-developer-controlled-wallets/SKILL.md), use-user-controlled-wallets (https://github.com/circlefin/skills/blob/master/plugins/circle/skills/use-user-controlled-wallets/SKILL.md), use-modular-wallets (https://github.com/circlefin/skills/blob/master/plugins/circle/skills/use-modular-wallets/SKILL.md), use-gateway (https://github.com/circlefin/skills/blob/master/plugins/circle/skills/use-gateway/SKILL.md), use-smart-contract-platform (https://github.com/circlefin/skills/blob/master/plugins/circle/skills/use-smart-contract-platform/SKILL.md). Full Circle developer docs: https://developers.circle.com/llms.txt.

# Error recovery and troubleshooting for bridges

> Identify bridge transfer failures, recover partial bridge transfers, and implement error handling for App Kit SDK bridge transfers

Bridge transfers can encounter two error types. Hard errors stop execution. Soft
errors let you recover and retry the bridge transfer. The App Kit SDK provides
error handling that helps you respond in both cases.

Hard errors throw exceptions such as validation errors, configuration issues,
and authentication problems. Soft errors occur during the bridge transfer but
return enough transaction information for recovery. Examples include
insufficient balance, network timeouts, and RPC connectivity issues.

This guide helps you identify failure points, recover partial bridge transfers,
and implement error handling patterns.

<Note>
  The examples below are focused recovery snippets, not complete runnable scripts.
  They assume you have already configured `kit`, `sourceAdapter`, and
  `destinationAdapter`. See [Adapter setups](/app-kit/tutorials/adapter-setups)
  for setup options.
</Note>

## Bridge transfer failures

This section explains how to identify where a bridge transfer failed and resume
the bridge transfer manually.

### Transaction steps overview

Each bridge transfer uses Circle's CCTP protocol provider, which breaks each
transaction into various steps:

* `approve`: Allows the contract to spend USDC.
* `burn`: Burns USDC on the source blockchain and generates an attestation.
* `fetchAttestation`: Waits for Circle to sign the burn proof.
* `mint`: Mints USDC on the destination blockchain with the attestation.

### Bridge result details

When a bridge transfer fails, the App Kit SDK returns a `BridgeResult` object
showing which steps completed and which failed. Use this result to decide
whether to retry the transfer, inspect a transaction on a block explorer, or
surface a recoverable state to your application.

Focus on these `BridgeResult` properties during recovery:

* `result.state` - shows whether the bridge transfer succeeded or failed
  (`pending`, `success`, `error`)
* `result.steps` - each object contains:
  * `name`: the name of the step
  * `state`: the status of the step
  * `txHash`: the transaction hash if the step completed
  * `error`: an error message if the step failed

This example shows a returned `result` object for a transaction that failed when
fetching an attestation:

```bash Shell theme={null}
result.state: 'error'
result.steps: [
  { name: 'approve', state: 'success', txHash: '0x123...' },
  { name: 'burn', state: 'success', txHash: '0x456...' },
  { name: 'fetchAttestation', state: 'error', error: 'Network timeout' },
]
```

### Step analysis

This example shows how to check for completed steps and use a helper function to
find specific steps:

```typescript TypeScript theme={null}
// Start a bridge transfer that might fail
const result = await kit.bridge({
  from: { adapter: sourceAdapter, chain: "Ethereum_Sepolia" },
  to: { adapter: destinationAdapter, chain: "Arc_Testnet" },
  amount: "1.00",
});

// Check which steps completed successfully
console.log("Bridge transfer state:", result.state);
console.log("Steps:", result.steps);

// Helper function to find specific steps
const getStep = (stepName: string) =>
  result.steps.find((step) => step.name === stepName);
const approveStep = getStep("approve");
const burnStep = getStep("burn");
const attestationStep = getStep("fetchAttestation");
const mintStep = getStep("mint");
```

## Recovery scenarios

This section describes how you can implement recovery patterns.

### Retry a failed bridge transfer

If a bridge transfer fails, you can retry it with the `retry` method. Pass the
failed `BridgeResult` and the `to` and `from` adapters.

This example shows how the retry method works:

```typescript TypeScript theme={null}
const result = await kit.bridge({
  from: { adapter: sourceAdapter, chain: "Ethereum_Sepolia" },
  to: { adapter: destinationAdapter, chain: "Arc_Testnet" },
  amount: "1.00",
});

if (result.state === "error") {
  const retryResult = await kit.retry(result, {
    from: sourceAdapter,
    to: destinationAdapter,
  });
  console.dir(retryResult, { depth: null, colors: true });
} else {
  console.dir(result, { depth: null, colors: true });
}
```

### Retry after a failed mint step

This pattern shows how to retry when the mint step fails. The
`failingDestinationAdapter` placeholder represents a bad destination signer or
RPC setup used to exercise the retry path:

```typescript TypeScript theme={null}
import type { BridgeResult } from "@circle-fin/app-kit";

const findErrorStep = (result: BridgeResult) => {
  if (result.state === "error") {
    return result.steps.find((step) => step.state === "error");
  }
  return null;
};

const result = await kit.bridge({
  from: { adapter: sourceAdapter, chain: "Ethereum_Sepolia" },
  to: { adapter: failingDestinationAdapter, chain: "Arc_Testnet" },
  amount: "1.00",
});

console.log("INITIAL RESULT");
console.dir(result, { depth: null, colors: true });

if (result.state === "error") {
  const errorStep = findErrorStep(result);
  if (
    errorStep &&
    errorStep.errorMessage?.includes("gas required exceeds allowance") // This is an example error message
  ) {
    const retryResult = await kit.retry(result, {
      from: sourceAdapter,
      to: destinationAdapter,
    });
    console.log("RETRY RESULT");
    console.dir(retryResult, { depth: null, colors: true });
  }
}
```

## Common issues

This section lists common issues and solutions.

### Insufficient balance

Ensure you have enough USDC in your wallet before a bridge transfer to avoid an
insufficient balance error.

This EVM example checks your wallet balance:

```typescript TypeScript theme={null}
import { formatUnits } from "viem";

const balanceAction = await sourceAdapter.prepareAction(
  "usdc.balanceOf",
  {},
  { chain: "Arc_Testnet" },
);
const balance = await balanceAction.execute();
console.log(`USDC balance: ${formatUnits(BigInt(balance), 6)}`);
```

### Transaction stuck or failed

If a transaction is stuck or failed, check the transaction on a block explorer
with the returned `txHash`. For Solana bridge transfers, use Solana Explorer or
SolScan.

If the transaction failed during the bridge transfer, check the returned
`result.steps` to see which [transaction steps](#transaction-steps-overview)
completed.

## Best practices

Follow these practices for prevention, recovery, and monitoring to improve
reliability.

**Prevention**

* Test your integration on testnets before deploying on mainnet.
* Monitor gas prices and adjust during network congestion.
* Use dedicated RPC providers such as Alchemy or QuickNode.
* Implement multiple RPC fallbacks.
* Wrap all bridge transfers in try-catch including adapter setup and bridge
  calls.

**Recovery**

* Always save the bridge transfer state for recovery scenarios.
* Verify which steps completed before attempting recovery.
* Use appropriate timeouts and give network operations enough time to complete.
* Implement exponential backoff and use increasing delays for retry logic.

**Monitoring and debugging**

* Use block explorers to verify transaction status.
* Save intermediate results and persist bridge transfer state for recovery
  scenarios.
