← Back to Blog

sniper

The Solana Bug That Failed 74% of My Sniper's Buys (and Lied About Why)

The Solana Bug That Failed 74% of My Sniper's Buys (and Lied About Why)

If your Solana transactions keep failing with Token-2022 "Invalid Mint" (custom error 0x2) or "transaction simulation failed" on brand-new accounts — and the mint is obviously valid — it's almost certainly your preflightCommitment. Here's the bug, the smoking gun, and the one-line fix.

The symptom

My memecoin sniper buys tokens that are seconds old. About three out of every four buys were failing — and the error was a lie.

The RPC rejected the transaction with Token-2022 "Invalid Mint" (0x2) / "transaction simulation failed." But the mint was fine. I could pull it up on an explorer. The bonding curve was live. My paper-trader was happily marking its price one process over. The token unquestionably existed.

The bot insisted it didn't.

Misleading errors are the worst kind, because you go debug the thing the error names — the mint, the token account, the Token-2022 program — and you lose hours, because the error is pointing at a symptom three layers from the cause.

The smoking gun

Instead of trusting the error text, I logged the age of the mint at each buy attempt and split by outcome:

The failure wasn't random. It correlated almost perfectly with how new the token was. That's not a "bad mint" problem. That's a time problem.

The cause: preflight simulates against a stale bank

When you call sendTransaction, the RPC runs a preflight simulation first — it executes your transaction against a recent bank and rejects it if it would fail, before broadcasting. Useful. Except the commitment level that simulation runs at defaults to finalized.

Finalized state lags the chain tip by ~13–30 seconds (~31+ slots back). So when I tried to buy a mint created 5 seconds ago, preflight simulated my buy against a finalized bank from ~20 seconds ago — a version of the chain where that mint account did not exist yet. The simulator looks up the mint, finds nothing, and returns the most local-feeling error it has: Token-2022 "Invalid Mint" (0x2).

The mint was valid. The bank the simulation chose to look at was too old to know about it. And the 12.4s-vs-28s split is simply the finalized-lag window showing up in the data — exactly where the theory says the cliff should be.

The fix (one line)

Tell preflight to simulate against the processed commitment — the most recent state, which does include seconds-old accounts:

# preflightCommitment "processed" is load-bearing: the RPC default is
# "finalized", which lags the tip by ~13-30s. We buy mints that are
# seconds old, so finalized-bank simulation can't see the mint yet and
# fails with Token-2022 "Invalid Mint" (0x2).
await rpc("sendTransaction", [b64, {
    "encoding": "base64",
    "skipPreflight": False,
    "maxRetries": 3,
    "preflightCommitment": "processed",   # <-- the whole fix
}])

That's it. The buy-failure rate collapsed.

A note on the alternative: you could also set skipPreflight: true and bypass simulation entirely. I didn't. Preflight at processed still catches real problems — insufficient SOL, blown slippage, a genuinely malformed transaction — and costs a few milliseconds. Skipping it would have fixed the symptom while throwing away a useful guardrail. processed keeps the guardrail and just points it at a bank that's actually current.

The lessons

  1. On Solana, preflight commitment matters for any transaction touching fresh accounts. The finalized default is a sensible, safe choice for ordinary apps — and a footgun for anything fast: snipers, new-pool LPs, mint-and-immediately-use flows.
  2. Trust the error's existence, not its content. "Invalid Mint" was technically true from the simulator's vantage point and completely useless as a diagnosis. The fix came from ignoring what the error said and measuring what the failures had in common.
  3. Log the thing you suspect, not the thing that's loud. The "Invalid Mint" line was loud and everywhere. A quiet number — mint age at buy time — was the one that actually split the data.

This bug ate a real chunk of the early sniper's buys before I caught it. The bot still doesn't have an edge at entry — that's a separate, more painful post — but at least now, when it loses, it loses on purpose instead of on a phantom error. You can watch the fixed version run, on real money, live.