# How to Handle Transaction Failures and Error Responses from the Osmosis Blockchain

> Learn to handle Osmosis blockchain transaction failures and error responses. Use try/catch, check BroadcastTxResponse code, and inspect rawLog for on-chain details.

- Repository: [Jon Ator/osmosis-agent-toolkit](https://github.com/jonator/osmosis-agent-toolkit)
- Tags: how-to-guide
- Published: 2026-03-05

---

**To handle transaction failures in the Osmosis Agent Toolkit, wrap `signAndBroadcast` calls in `try/catch` blocks, inspect the `BroadcastTxResponse` for non-zero `code` values, and check `rawLog` for on-chain error details.**

The Osmosis Agent Toolkit provides a high-level `Account` class in [`packages/core/src/account.ts`](https://github.com/jonator/osmosis-agent-toolkit/blob/main/packages/core/src/account.ts) that abstracts Cosmos SDK transaction signing and broadcasting. When you submit transactions to the Osmosis blockchain, the toolkit exposes raw error responses that require explicit handling to distinguish between network failures, simulation errors, and on-chain rejections.

## Understanding the Transaction Flow in Osmosis Agent Toolkit

### The Account.signAndBroadcast Method

In [`packages/core/src/account.ts`](https://github.com/jonator/osmosis-agent-toolkit/blob/main/packages/core/src/account.ts) (lines 107-115), the `Account` class implements the `signAndBroadcast` method, which internally instantiates a `SigningStargateClient` and calls `signAndBroadcastSync`. This method returns a `BroadcastTxResponse` object containing the transaction hash, block height, and critical error metadata.

```typescript
// Simplified flow from account.ts
const client = await SigningStargateClient.connectWithSigner(
  this.rpcEndpoint,
  this.wallet,
  this.clientOptions
);
const response = await client.signAndBroadcastSync(signerAddress, messages, fee, memo);

```

### The BroadcastTxResponse Structure

When CosmJS processes your transaction, it returns a `BroadcastTxResponse` with these key fields:

- **`code`**: `0` indicates success; non-zero values indicate specific failure types (e.g., code `5` typically means insufficient funds).
- **`rawLog`**: A human-readable string containing the detailed error message from the Osmosis chain.
- **`txhash`**: The transaction hash (present even for failed transactions that made it on-chain).

### Tool Layer Integration

Higher-level tools like `SendSwapInGivenOutQuoteTxTool` call `account.signAndBroadcast` internally. In [`packages/core/src/tools/swap.ts`](https://github.com/jonator/osmosis-agent-toolkit/blob/main/packages/core/src/tools/swap.ts) (lines 244-252), these tools typically extract only the `txHash` from the response, swallowing the full error details unless you modify the implementation.

## Common Blockchain Transaction Failure Modes

### Simulation and Fee Estimation Errors

Before broadcasting, the toolkit calls `estimateFee` (implemented near line 258-268 in [`account.ts`](https://github.com/jonator/osmosis-agent-toolkit/blob/main/account.ts)) to simulate the transaction. If the simulation fails—due to invalid parameters or insufficient gas settings—CosmJS throws an exception before any `BroadcastTxResponse` is generated.

### Network and RPC Broadcast Failures

Connectivity issues trigger runtime errors with messages like *"No RPC endpoint found"* (see [`account.ts`](https://github.com/jonator/osmosis-agent-toolkit/blob/main/account.ts) line 202). These manifest as thrown JavaScript `Error` objects rather than structured response codes.

### On-Chain Transaction Rejections

When a transaction reaches the Osmosis blockchain but fails execution (e.g., slippage tolerance exceeded, invalid pool ID, or out-of-gas), the node includes the transaction in a block with a non-zero `code`. The `rawLog` field contains the specific error message from the Cosmos SDK module.

## Best Practices for Error Handling

### Wrapping Tool Calls in Try-Catch Blocks

Always wrap tool invocations in `try/catch` to capture both network errors and unexpected runtime failures:

```typescript
import { SendSwapInGivenOutQuoteTxTool } from '@osmosis-agent-toolkit/core';

async function executeSwap(tool: SendSwapInGivenOutQuoteTxTool, params: object) {
  try {
    const { txHash } = await tool.call(params);
    console.log(`✅ Tx submitted: ${txHash}`);
    return txHash;
  } catch (err) {
    if (err instanceof Error) {
      console.error('⚠️ Broadcast failed:', err.message);
      // Handle RPC errors or simulation failures
      throw err;
    }
  }
}

```

### Inspecting BroadcastTxResponse for Failure Codes

For granular error diagnostics, bypass the high-level tool abstraction and interact directly with the `Account` class to access the full `BroadcastTxResponse`:

```typescript
import type { BroadcastTxResponse } from '@cosmjs/stargate';
import { Account } from '@osmosis-agent-toolkit/core';

async function broadcastWithErrorHandling(
  account: Account,
  messages: EncodeObject[]
): Promise<BroadcastTxResponse> {
  const resp = await account.signAndBroadcast({ msgs: messages });
  
  if (resp.code !== 0) {
    console.error('❌ Transaction failed');
    console.error('Error Code:', resp.code);
    console.error('Details:', resp.rawLog);
    // Implement retry logic or user notification here
  } else {
    console.log('✅ Success:', resp.txhash);
  }
  return resp;
}

```

### Distinguishing Network Errors from On-Chain Failures

Structure your error handling to differentiate between pre-broadcast exceptions and post-broadcast failures:

1. **Network/SDK errors**: Thrown as JavaScript `Error` objects during `signAndBroadcast` (RPC unreachable, simulation failed).
2. **On-chain failures**: Returned as valid `BroadcastTxResponse` objects with `code !== 0` (insufficient funds, invalid state).

## Practical Implementation: Handling Swap Transaction Failures

This complete example demonstrates robust error handling for swap operations using the `SendSwapOutGivenInQuoteTxTool`:

```typescript
import { Account, SendSwapOutGivenInQuoteTxTool, ToolMemory } from '@osmosis-agent-toolkit/core';
import type { SidecarOutGivenInQuoteResponse } from '@osmosis-agent-toolkit/core';

const mnemonic = process.env.OSMOSIS_MNEMONIC!;
const account = new Account(mnemonic);
const memory = new ToolMemory<string, SidecarOutGivenInQuoteResponse>();
const swapTool = new SendSwapOutGivenInQuoteTxTool(account, memory);

const params = {
  quoteId: 'abc123',
  slippageTolerancePercent: 0.5,
};

async function runSwap() {
  try {
    const result = await swapTool.call(params);
    console.log('✅ Swap submitted, txHash:', result.txHash);
  } catch (error) {
    if (error instanceof Error) {
      console.error('🚨 Network or simulation error:', error.message);
      // Likely RPC failure or fee estimation failure (account.ts L258-268)
    } else {
      console.error('🚨 Unknown error:', error);
    }
  }
}

runSwap();

```

To access the full `BroadcastTxResponse` including error codes, extend the tool or call `account.signAndBroadcast` directly as shown in the previous section.

## Summary

- Wrap every transaction broadcast in `try/catch` blocks to catch CosmJS network errors and simulation failures.
- Inspect `BroadcastTxResponse.code` where `0` equals success and non-zero indicates specific on-chain failures.
- Read `BroadcastTxResponse.rawLog` to extract human-readable error messages from the Osmosis blockchain.
- Handle `estimateFee` errors separately; these throw exceptions before the transaction reaches the network.
- For complete error diagnostics, call `Account.signAndBroadcast` directly rather than relying on tools that return only the transaction hash.

## Frequently Asked Questions

### What error code indicates insufficient funds in Osmosis?

Error code `5` typically indicates insufficient funds or insufficient fees in Cosmos SDK chains including Osmosis. When you receive a `BroadcastTxResponse` with `code: 5`, check the `rawLog` field for details about the specific denomination and amount required.

### How do I access the full error message when a transaction fails on-chain?

Instead of using high-level tools that return only `{ txHash }`, call `account.signAndBroadcast({ msgs })` directly from [`packages/core/src/account.ts`](https://github.com/jonator/osmosis-agent-toolkit/blob/main/packages/core/src/account.ts). The returned `BroadcastTxResponse` object contains the `rawLog` property with the complete error message from the blockchain.

### Should I catch errors at the tool level or the Account level?

Catch errors at the outermost application layer that invokes the toolkit. The tools in [`packages/core/src/tools/swap.ts`](https://github.com/jonator/osmosis-agent-toolkit/blob/main/packages/core/src/tools/swap.ts) propagate both thrown exceptions (network errors) and successful responses, so wrapping the `tool.call()` or `account.signAndBroadcast()` invocation in a single `try/catch` block handles all failure modes.

### What is the difference between signAndBroadcast and signAndBroadcastSync?

According to the CosmJS implementation used in [`account.ts`](https://github.com/jonator/osmosis-agent-toolkit/blob/main/account.ts) (line 115), `signAndBroadcastSync` submits the transaction and returns immediately once it is included in the mempool, providing a `BroadcastTxResponse`. The `signAndBroadcast` method in the Osmosis Agent Toolkit wraps this call and returns the same response type, allowing you to handle both synchronous validation errors and asynchronous on-chain failures through the `code` and `rawLog` fields.