Troubleshooting
Symptom-first diagnosis for the Solana chain module — the devnet fall-through, deposits that never credit, SPL withdrawals failing while native ones clear, TIMEOUT rows, and rate-limit symptoms.
Start with the diagnostics: Admin → Ecosystem → Blockchains → Requirements, select Solana, run the test. It prints the cluster it actually resolved to, which is the single most common answer on this chain, and it reports readiness per flow rather than per endpoint.
If the vault is locked or the master wallet is missing, the test reports withdrawals as failed even when the RPC is perfectly healthy. That is deliberate: an RPC that answers is not a pass if a customer still cannot get their money out.
Fast triage
| Symptom | Most likely cause |
|---|---|
| Deposits never arrive, everything else looks fine | SOL_NETWORK resolved to devnet |
| "Solana service not available" on every action | Licence file missing, chain row disabled, or the service files are not installed |
| Enabling the chain returns 403 | lic/54514052.lic is absent — activate the licence first |
| Solana is not offered when creating a token or master wallet | The chain row is still disabled |
| SOL deposits credit, SPL deposits do not | The token's contract is not the correct SPL mint address |
| Deposits detected but never credited | The Ecosystem cron process is not running, or Redis lost the pending record |
| SPL withdrawals fail, native SOL withdrawals succeed | The master wallet is empty or disabled |
Withdrawals sit at PENDING and never sign |
The vault is locked in the process handling them |
A withdrawal row shows TIMEOUT |
Broadcast but unverifiable — a human must settle it |
| A customer received slightly less SOL than requested | Network-fee reservation on a full-balance withdrawal |
| A token disappeared shortly after you created it | The background initial mint failed and deleted the row |
| Transaction history shows zero amounts and no counterparty | That view parses native transfers only |
| Everything is slow and intermittent | The public cluster is rate-limiting you |
Diagnosis in detail
Check the cluster before anything else. SOL_NETWORK recognises only the
literal strings mainnet and testnet; unset, misspelled, or set to
mainnet-beta, it resolves to devnet with no error anywhere.
On devnet everything appears healthy. Addresses generate, the diagnostics pass their RPC checks, the deposit page renders. The customer's mainnet SOL simply sits at an address the platform is watching on a different network.
Open the requirements test and read the Cluster resolution line — it prints
the resolved endpoint. Fix SOL_NETWORK, then pm2 restart backend, because the
connection is built once at module load and cached.
Addresses generated while the wrong cluster was configured are still valid
keypairs and the funds at them are still reachable, but their stored network
label will be wrong until they are regenerated.
An ECO wallet is one row per user per currency, and each one has its own Solana keypair. A user holding SOL and USDC has two different Solana addresses.
Tokens sent to the address shown on the SOL deposit page land at an address the platform controls, under a wallet whose currency is SOL. Nothing watches that address for that mint, so nothing credits it. The funds are recoverable because the key exists, but only through manual operator work against the database.
There is no automatic recovery path for this. The prevention is interface discipline: the address on the deposit page is for the asset on that page.
Three independent conditions produce this message, and the requirements report distinguishes them:
No licence file. lic/54514052.lic must exist under the project root. The
service-side check caches its result for five minutes, so an activation done
while the backend is running is not visible immediately.
The chain row is disabled. Admin → Ecosystem → Blockchains, find the Solana
row (product ID 54514052) and enable it. It ships with status: false.
The service files are not installed. If backend/src/blockchains/sol.ts is
absent — usually because the addon was never extracted, or an update left a
partial install — the diagnostics report "Chain service installed: no" and the
licence is irrelevant. Reinstall the addon files.
"Cannot enable blockchain: License not activated." The toggle checks for the
licence file before it will write status = true, and this check is not cached.
Activate the licence, confirm lic/54514052.lic exists, and try again.
Native and SPL detection are entirely different mechanisms, so one working tells you nothing about the other.
Check the token's contract field first. On Solana it must be the SPL mint address. An invalid value makes the monitor refuse to start, with a log line naming the token and telling you to fix it in the ecosystem token settings — no SPL deposit for that token will ever be detected until it is correct.
Then check that the token is active. An inactive token is skipped when addresses are issued and when monitors are built.
Then confirm the customer sent the right mint. The subscription is filtered to one mint and one owner; a different token with a similar ticker is a different mint and will not match.
Detection and crediting are separate. Detection writes a pending record into
Redis; verifyPendingEcoDeposits credits it on a 60-second pass.
Check Admin → System → Cron that the job is registered and running. If the whole Ecosystem job group is missing, the extension is disabled or the cron process did not pick up the change.
If the job is running, look for the pending record. Between detection and crediting the deposit lives in Redis, not MySQL. A Redis flush in that window loses it — the coins are still at the customer's address and will be found on the next scan of that address, but only if the address is still in the background scanner's 72-hour working set. Otherwise nothing happens until the customer opens the deposit page again.
Solana does not wait for a confirmation depth. If a deposit is pending and the cron is running, the delay is not a confirmations problem.
Is the vault unlocked? Signing needs key material. /admin/ecosystem shows
Initiate Vault when locked. On a multi-process deployment the unlock is per
process — a green badge on the process that served your admin request does not
mean the process handling the withdrawal is unlocked.
Does a Solana master wallet exist, and is it enabled? A disabled master wallet behaves exactly like a missing one and the diagnostics downgrade withdrawal readiness to failed for either.
Is the queue moving at all? Solana withdrawals are serialised behind a five-second per-chain cooldown, so a deep queue has a long tail by design. Fifty pending rows is roughly four minutes even when everything succeeds.
If a row was debited and the process restarted before the queue picked it up, the boot-time sweep re-enqueues it. Nothing is lost; it may just be waiting.
The master wallet is the fee payer for every SPL withdrawal and for creating any associated token account the transfer needs. Native SOL withdrawals are signed by the customer's own address and never touch it.
So an empty or disabled master wallet produces exactly this split. Top it up with SOL, allowing headroom for account creation on top of the transaction fee — sending a token to a recipient who has never held it costs more than sending it to one who has.
Also check the error text. "Master wallet not found or invalid" is a missing or undecryptable master wallet; "Insufficient SPL token balance" means the customer's own token account really is short, which points at a crediting or reconciliation problem rather than a gas one.
TIMEOUT means the transaction was broadcast and the platform then could not
confirm or verify it within ten retries. It is deliberately not FAILED, because
marking it failed would refund money that may already have left.
Resolve it by hand:
- Take the signature from the transaction row.
- Look it up on
explorer.solana.comfor the cluster you are running. - If it succeeded, settle the row as completed. If it never landed, the funds are still with you and the row can be failed and refunded.
A TIMEOUT queue that keeps growing is not a bug to chase individually — it is
the public cluster failing to keep up with your withdrawal volume. See
Network and RPC.
On a native SOL withdrawal the network fee is paid out of the same balance being sent. The platform reads the on-chain balance, subtracts the fee it priced for the transaction, and if the requested amount exceeds what is left it reduces the broadcast amount rather than failing.
This only happens on a full-balance withdrawal, and the shortfall is the network fee — a few thousand lamports. Configure a non-zero minimum fee on the SOL token so a max-out withdrawal always leaves headroom.
Deploying an SPL token creates the mint immediately and mints the initial supply as a background job. If that job fails after its retries, it deletes the token row it was minting for, so the token disappears from the admin list while the mint itself still exists on-chain.
The usual cause is the master wallet running out of SOL between the two steps — creating the mint, creating the holder's associated token account and minting all cost lamports. Fund the master wallet and deploy again.
That view fetches the last 50 signatures for an address and parses System Program transfers only, so an address whose activity is entirely SPL renders rows with no counterparty and a zero amount. It is a display limitation, not a detection failure — the balance and the platform's own transaction records are correct.
Results are also cached in Redis for 30 minutes per address, so a freshly credited deposit can be absent from the list while the balance has already moved.
Verify against the signature on explorer.solana.com rather than treating this
view as authoritative.
The Solana service always uses the public cluster RPC. There is no custom RPC
setting — SOLANA_RPC_URL is read only by the admin cost estimate, and
SOL_<NETWORK>_RPC is read by a status badge and nothing else.
Symptoms escalate in a predictable order: transaction history goes stale, live
deposit detection stops while background detection continues, withdrawal
confirmation slows and then produces TIMEOUT rows, and finally broadcasts
start failing.
What you can do: lower ECOSYSTEM_SCAN_ACTIVE_TTL_MS so fewer addresses are
being swept, lengthen ECOSYSTEM_SCAN_INTERVAL_MS, and leave
ECOSYSTEM_SCAN_RATE_SOL alone unless you have evidence the cluster tolerates
more. Raising the rate produces more 429s, which the scanner logs and skips past
— and skipped scans look exactly like missing deposits.
The chain options list adds Solana only when its ecosystem_blockchain row
exists and is enabled. Enable the row, then reload the admin page.
If the row is enabled and Solana still does not appear, the extension list is stale — restart the backend.
Related
- Install and enable — the setup order that avoids most of this
- Network and RPC — cluster resolution and rate limits
- Deposits — the detection paths in full
- Withdrawals and fees — signing, fees and statuses
- Ecosystem: troubleshooting — vault, cron and platform-wide issues