Failed transaction in.
Working transaction out.
TxWhy finds the exact reason a Solana transaction failed, rebuilds it, and proves the rebuilt one works by simulating it against live chain state. For people, bots and AI agents.
Not sent yet? Repair it before you send, or watch a live demo →
Why this exists
On a busy day somewhere between one in eight and one in two Solana transactions fail. Bots and agents fail more than half of what they send, and the priority fee is burned every time. What they get back is a code like Custom(6001). Explorers and AI explainers tell you what happened. TxWhy hands you the transaction that works.
How it works
01
Diagnose
Replays the transaction, walks every inner call, and pins the exact step that broke and why.
02
Rebuild
Applies the fix that matches the cause and leaves everything else exactly as you wrote it.
03
Prove
Simulates the rebuilt transaction on live state. You only get it back if it passes.
The rebuilt transaction comes back unsigned. You sign it with your own wallet. TxWhy never sees a key.
What it handles today
- Fixes
Blockhash expired
Replaced with a current one. We check whether the original had really expired.
- Fixes
Compute budget exceeded
We run the transaction with the maximum budget, read what it truly used, and set the limit to that plus headroom.
- Fixes
Dropped under load
Priority fee set from what the network recently charged for the exact accounts you write to.
- Fixes
Slippage on a Jupiter swap
Only the swap instruction is replaced with a freshly quoted one. Your tokens, amount, tolerance and every other instruction stay exactly as written, and we show how the minimum you receive changed.
- Fixes
Loaded account data limit too small
Lifted when the transaction declares a limit smaller than what it actually loads.
- Fixes
Slippage on a direct Pump.fun, PumpSwap or Raydium swap
These instructions carry no tolerance, only a limit. The amount and every account stay as written; only the limit moves to the current price using the programs' own math, with a stated 1% tolerance and never more than 25% against you.
- Fixes
Version 1 transactions (the new format)
SIMD-0385 went live on mainnet on Sep 15, 2026 and moved compute settings into the transaction header. TxWhy reads and rebuilds v1 natively: the same repairs, applied to the header, re-encoded with @solana/kit.
- Explains
Not enough SOL
Not something a rebuild can fix. We give you the exact shortfall instead.
- Explains
A program rejected it
Named cause and fix from the program's own published errors, where they exist.
When something cannot be fixed by rebuilding, TxWhy says so. It will never hand back a transaction that would fail again.
One line in your send loop
Most failures happen at simulation, before anything is sent. So that is where the repair belongs. If your transaction passes, it is signed and sent and TxWhy is never contacted. If it would fail, it comes back rebuilt, is checked on your machine, and only then reaches your signer.
npm i @txwhy/sdk
import { sendWithRepair } from "@txwhy/sdk";
// simulate -> repair if it would fail -> verify locally -> sign -> send
const { signature, repairs } = await sendWithRepair(
connection,
transaction,
(tx) => wallet.signTransaction(tx), // your keys never leave your process
);From a terminal: npx @txwhy/sdk <signature>
On @solana/kit? The same loop, with no web3.js and with version 1 transactions included: import { sendWithRepair } from "@txwhy/sdk/kit" and pass your rpc, the transaction and your signer.
Proof, on chain
Two transactions on Solana mainnet you can open yourself. No screenshots, no staging.
A repaired transaction that landed
An agent built a swap on a stale quote. Without TxWhy it failed simulation with
5BaKDPgC…zXhymq on Solscan →0x1771. With one line, it was rebuilt from a fresh quote for the same trade, verified locally (four instructions untouched, same payer, same signers), signed by the agent, and landed in slot 449,732,359.An agent that paid for a repair
$0.001 in USDC over x402 for a verified slippage repair, settled only after the answer came back, network fee paid by the facilitator. No account, no API key.
2t4hz3zm…AcAUzrA on Solscan →
You never have to trust us
Signing a transaction that a server rebuilt should make you nervous. So every repair comes with a proof, and the check behind it is open source, has no network access, and runs on your machine. A repaired transaction may differ from yours in exactly three ways:
- compute budget settings (limit, priority fee, loaded data size)
- one Jupiter swap instruction replaced by another for the same wallet, the same source and destination token accounts, the same output token, the same amount and the same slippage tolerance
- the recent blockhash
Same fee payer, same signers, every other instruction byte for byte and in the same order. Anything else is refused. The test suite attacks it fifteen ways: an extra transfer, a redirected fee, a new signer, a widened slippage, swap proceeds sent to a stranger. All fifteen are caught. TxWhy runs the same check on its own output and will not return a transaction that fails it.
import { verifyRepair } from "@txwhy/sdk";
const check = await verifyRepair(connection, original, repaired);
if (!check.ok) throw new Error(check.violations.join(" ")); // never sign itFree for people. A tenth of a cent for agents.
The website, the bot and /api/v1/repair are free and rate limited. Agents that need guaranteed capacity call /api/x402/repair instead: $0.001 in USDC per repair over x402, no account, no API key, charged only when the answer succeeds. A repaired transaction that lands costs less than the priority fee on one that does not.
For agents and bots
One call inside your send loop. When your RPC rejects a transaction at simulation, pass it here and get back a version that passes, typically in under a second. Most failures never reach the chain. They happen at this step, and this is where TxWhy sits.
curl -X POST https://txwhy.vercel.app/api/v1/repair \
-H "content-type: application/json" \
-d '{"transaction": "<base64, signed or unsigned>"}'{
"status": "repaired",
"cause": { "title": "Compute budget exceeded", ... },
"changes": [
{ "type": "compute_unit_limit", "before": "100", "after": "518" }
],
"repairedTransaction": "<base64, unsigned>",
"simulation": { "passed": true, "unitsConsumed": 450 }
}Or plug it into any agent as a tool
TxWhy is an MCP server. Add the URL and your agent gets three tools: repair_transaction, diagnose_transaction and explain_error. No key, no account.
{
"mcpServers": {
"txwhy": { "url": "https://txwhy.vercel.app/api/mcp" }
}
}You can also pass {"signature": "..."} for a transaction that already landed and failed. Status is one of repaired, valid, needs_requote or not_repairable.