Almost every losing bot session traces to one of eight causes: late detection, failed landing, slippage blowout, weak token filtering, insufficient rent or fee headroom, key exposure, RPC throttling, or unhandled pool migration. Each has a distinct signature. The diagnostic discipline is to identify which one is producing the loss before changing any setting, because the fixes point in opposite directions and guessing usually makes things worse.
The failure matrix
Read this table first and use the detail sections as reference. The most valuable column is the third: the observation that separates this failure from the others that look like it.
| Failure mode | Symptom the operator sees | What distinguishes it | Fix |
|---|---|---|---|
| Late detection | Fills consistently several blocks after the open | Landing rate is healthy; entry prices are poor | Change the data path, not the fee policy |
| Failed landing | Trades that simply did not happen | Signatures absent from chain entirely | Fee level, endpoint quality, blockhash freshness, retry cadence |
| Slippage blowout | Position opens far above the quoted price | Transaction landed and succeeded; realised price differs from quote | Tighter tolerance, fresher quotes, smaller size relative to depth |
| Weak token filtering | Repeated entries into tokens that cannot be exited | Execution metrics are all healthy; outcomes are not | Pre-entry checks, including a simulated sell |
| Rent and fee headroom | Failures that cluster on the first trade from a wallet | Error names an account that could not be created or funded | Fund wallets with an explicit reserve above trading capital |
| Key exposure | Funds leave outside the bot's own activity | Transactions the operator did not initiate | Containment first, rotation second, forensics last |
| RPC throttling | The bot goes quiet exactly during busy periods | Errors correlate with market-wide activity, not with a token | Request budget, caching, fallback endpoint |
| Unhandled migration | Sells fail after a market moves venue | Route points at a venue that no longer holds the liquidity | Re-resolve the route at exit time rather than caching it |
One: late detection
The bot works, lands its transactions, and still buys at prices that look nothing like the opening. The tell is the combination of a healthy landing rate with consistently poor entry prices: the pipeline is fine, the information reaching it is old.
Causes are almost always in the data path. Polling on an interval means an average delay of half that interval. A shared WebSocket endpoint queues notifications during exactly the bursts that matter. A third-party aggregator adds its own processing and cache before it tells you anything, and it tells everyone else at the same time.
The diagnostic is a timestamp comparison: record when your process learned about an event and compare it against the block time of the slot in which that event occurred. Do this for a few hundred events and read the distribution. If the median is large, the source is the problem. If the median is fine but the tail is bad, you have a queueing problem under load, which is a provider or plan-tier problem.
Late detection is also frequently a misunderstanding of what stage of a launch you are actually seeing. Different phases of a token's life emit different on-chain events, and a filter written against one phase will see the next one late by construction. Readers working specifically on curve launches will find the phase sequence set out in the Pump.fun launch timeline, which is the level of detail needed to know which event a filter should be listening for.
The fix is ordered: fix the source, then the transport, then the parsing. Spending on fees to compensate for late data is the most common wasted expenditure in this field.
Two: failed landing
The trade never happened. There is no signature on chain, no fee paid, and no error beyond whatever your own code logged. Because nothing is charged, this failure is invisible in a profit and loss statement and shows up only as opportunities that did not convert.
The distinguishing check is trivial: take the signatures your bot produced and query their status after the validity window has closed. Anything unknown never landed. If that share is significant, the problem is the submission path, and the causes are covered in detail in transaction landing on Solana: expired blockhashes, saturated ingress, fees too low for a contended account, or an endpoint that lags the cluster.
The reason this mode deserves its own entry is psychological rather than technical. Operators experience missed trades as bad luck or as the market being unfair, and they respond by increasing size on the trades that do land, which compounds the damage. Measuring landing rate converts an emotional narrative into a fixable engineering number.
Three: slippage blowout
The transaction landed, succeeded, and filled at a price far worse than quoted. This is the failure that produces the largest single losses, because a loose slippage tolerance is an instruction to accept almost any price.
Two mechanisms combine. First, the quote is stale: it was computed against pool state that other transactions have already changed. Second, the tolerance is set generously so that transactions do not fail, which is precisely the setting that converts a failed trade into an expensive completed one.
There is an unavoidable trade-off here, and it should be made explicitly rather than by default. Tight tolerance means more transactions revert, paying fees for nothing. Loose tolerance means fewer reverts and worse fills. The correct posture differs by direction: entries can afford to fail, because another opportunity exists; exits often cannot, because the alternative to a bad fill is no exit at all.
The measurement that makes this manageable is realised versus quoted price, parsed from the confirmed transaction's balance changes rather than from your own quote. Track it per trade and take the distribution seriously. A tolerance set at a level you have never actually hit is not protecting you; it is documenting that you have never been tested.
Four: weak token filtering
Every execution metric is healthy. Detection is fast, landing is reliable, slippage is controlled, and the account still bleeds. The failure is upstream of execution entirely: the bot is buying things it should not buy.
Filters fail in three characteristic ways. They check only the cheap things, such as a name pattern or a liquidity threshold, and miss authority configuration. They check state at the moment of entry and assume it is permanent, missing authorities that can be reintroduced or metadata that can be changed afterwards. Or they check the buy path only, never establishing that a sell path exists at all.
The last one is the most consequential and the easiest to fix: simulate a sell before submitting the buy. A simulated exit that fails is the single strongest signal available before committing funds, and it catches an entire family of constructions that no name-based or liquidity-based filter will see. The full set of checks, with what each one can and cannot prove, is in pre-entry safety checks.
Note the honest limit. Filters describe program state. They cannot describe intent, and the majority of losses in this category come from tokens that were technically clean and simply abandoned.
Five: rent and fee headroom
A wallet holds what looks like enough capital and the transaction still fails. The clue is that failures cluster on a wallet's first interaction with a given mint.
Two obligations get overlooked. Holding a token requires an associated token account, and that account must be rent-exempt, which currently costs on the order of 0.002 SOL locked per mint held. Wrapping SOL creates another account with the same requirement. Neither is a fee: it is a deposit, recoverable when the account is closed, but unavailable while it is open.
An illustrative calculation shows why this bites at scale rather than individually. A wallet touching 40 distinct mints has roughly 0.08 SOL immobilised in account rent, before any fees, plus fee headroom for base and priority fees across all its transactions. A fleet of 30 such wallets has locked several SOL in deposits that the operator probably believes are trading capital. Substitute your own mint count and wallet count; the structure of the arithmetic is the point, not the figures. The line surprises operators hardest when they move from a single sniper wallet to a volume bot for Solana, where a wallet fleet is the design rather than an accident and the immobilised deposit scales directly with it.
Two operational habits fix this permanently. Fund each wallet with an explicit reserve above the trading allocation, sized to cover account creation plus fees for the session rather than one transaction. And close token accounts for positions you have fully exited, which reclaims the deposit. The second habit is skipped almost universally, and it quietly accumulates.
Six: key exposure
Funds move in transactions your bot did not initiate. This is not a trading failure and it must not be handled like one.
The realistic exposure paths, in rough order of frequency: a private key pasted into a hosted interface, a key committed to a repository or left in a shell history, a key written into a log line during debugging, a malicious dependency in the bot's own toolchain, and a wallet approval granted to a program the operator did not evaluate.
The response order matters and is counter-intuitive under stress. Contain first by moving remaining funds to a wallet whose key has never touched the compromised environment. Rotate second. Investigate third. Operators routinely invert this, spending the critical minutes reading explorer history while the drain continues.
Prevention is structural rather than behavioural: segment wallets so that the key an automated system holds controls only what a session needs, keep the treasury on a signer that never touches an internet-connected bot process, and treat every key that has ever been in a hosted environment as permanently disclosed. The custody models and their blast radius are set out in keys, wallets and bot permissions.
Seven: RPC throttling
The bot is responsive in testing and goes quiet exactly when a market gets busy. The distinguishing feature is that errors correlate with chain-wide activity rather than with any particular token or venue.
Throttling can present as explicit rejections, or as silent queueing that looks identical to network latency. The latter is worse, because it produces no error to alert on and instead degrades every timing measurement at once.
Fixes are ordered by cost. Reduce demand first: cache immutable data, batch status queries, and move steady monitoring onto subscriptions. Add a fallback endpoint second, with health checks that route around a failing primary. Upgrade the plan tier last, once you know the real peak request rate rather than the average. The measurement procedure is in RPC choice and latency.
Eight: unhandled migration
A position entered on one venue becomes unsellable through the route the bot knows about, because the liquidity has moved. This happens by design on launchpads where a market graduates from an initial curve into a conventional pool, and it also happens whenever a project migrates liquidity or a venue upgrades its program.
The mechanism is a cached assumption. The bot resolved a route at entry, stored it with the position, and reuses it at exit. After migration that route points at a venue holding little or no liquidity, so the sell either fails or executes against negligible depth at a catastrophic price.
The fix is a design rule rather than a setting: never cache a route across the life of a position. Re-resolve at exit time, verify that the resolved pool holds meaningful depth before submitting, and treat a venue change as a routine event rather than an exception. A bot that cannot exit through a different venue than it entered on is not a trading system, it is a one-way instrument.
A post-mortem template
Run this after any session that lost money in a way you did not expect. It takes about twenty minutes and it distinguishes all eight modes without requiring new tooling.
- Count submitted signatures and confirm how many appear on chain. This isolates failed landing immediately.
- For landed transactions, split executed from failed-on-chain and read the actual program errors rather than summarising them.
- For executed buys, compute realised versus quoted price and inspect the distribution, not the average.
- Compare your detection timestamps against the block times of the triggering events for the same session.
- Check whether failures cluster on first contact with a mint, which points at account creation and rent.
- Check whether errors cluster in time with market-wide activity, which points at throttling rather than strategy.
- List every position that could not be exited and identify whether the venue changed after entry.
- Confirm that every outgoing transaction in the session was initiated by your own process.
- Write one sentence naming the dominant failure mode, and change exactly one thing before the next session.
The last item is the discipline that makes the rest useful. Changing several settings at once after a bad session guarantees that you learn nothing from the next one, and it is how operators end up with a configuration nobody can explain, tuned against a failure that was fixed months ago.