Skip to main content
Source: Full executable TypeScript in contract/src/examples/05-error-handling/. This page summarizes the flow — read the source for complete per-step code.

The Story

Kai is a frontend developer at ArtFund, responsible for building the campaign management interface. Before any transaction is sent to the blockchain, Kai wants to:
  1. Preview the outcome — simulate the transaction against the current chain state to see if it would succeed
  2. Show clear error messages — if the transaction would fail, explain why in plain language and suggest what to do
  3. Estimate the cost — display the gas estimate so users know what they will pay before confirming
Kai also needs to handle edge cases that come up in production: What happens when a user without the right permissions tries to perform a restricted action? What about users browsing the app without a connected wallet? How should the UI handle a read-only session? These patterns are essential for any production application built on Oak Protocol. A good error handling strategy turns cryptic blockchain reverts into helpful user-facing messages.

Steps

Step 1: Simulate Before Sending

Simulation calls the contract against the current chain state without broadcasting a transaction. If the simulation succeeds, the real transaction is safe to send. The simulation result includes the predicted return value and gas estimate.

Step 2: Prepare Transaction for External Signing

For account-abstraction wallets, Safe multisig, or custom signing flows, use toPreparedTransaction to extract raw transaction parameters (to, data, value, gas) from a simulation result.

Step 3: Catch Typed Errors

When a transaction reverts, the SDK decodes the raw revert data into a typed error class with a human-readable recovery hint. Three patterns:

Step 4: Handle Read-Only Client

When using a read-only client (no private key), write methods throw immediately with "No signer configured" without making an RPC call. Build your UI to handle this gracefully and prompt the user to connect their wallet.

Step 5: Safe Transaction Pattern

A reusable pattern that simulates a transaction, shows the user what will happen, and only sends after simulation passes. Reverts are caught and displayed as user-friendly error messages.

Step 6: Simulate With Error Decode

simulateWithErrorDecode wraps simulation and error parsing into a single convenience call. If simulation succeeds it returns the SimulationResult; if it reverts it throws a typed error with a recoveryHint property — no manual getRevertData / parseContractError needed.