> For the complete documentation index, see [llms.txt](https://docs.fast.poker/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.fast.poker/for-operators-dealer-service/troubleshooting.md).

# Troubleshooting

Dealer Service error meanings and operator actions.

## TEE and L1 error codes

| Code                     | Name                                          | What it means                                                 | Operator action                                                                                 |
| ------------------------ | --------------------------------------------- | ------------------------------------------------------------- | ----------------------------------------------------------------------------------------------- |
| `InvalidWritableAccount` | DLP                                           | A writable account in the TX is not delegated to the TEE      | Re-delegate that account; if it is supposed to live on L1, undelegate first then resubmit on L1 |
| `3007`                   | AccountOwnedByWrongProgram                    | Account is in transition between TEE and L1                   | Wait 5 to 15 seconds for absorption, then retry                                                 |
| `6021`                   | InvalidActionForPhase                         | Phase changed between the dealer's read and write             | Re-read the table state and re-evaluate; this is normal under contention                        |
| `6022`                   | NotPlayersTurn                                | The submitted player action is not for the current actor      | Re-read the table state and submit only for the current player                                  |
| `6042`                   | InvalidAccountCount                           | Account list does not match expected active-seat set          | Re-read seat states and resubmit with exact set                                                 |
| `6084`                   | NonceAlreadyProcessed                         | Cashout already processed (another dealer beat you to it)     | Skip to next pipeline step; this is not an error                                                |
| `6099`                   | (reused) PermissionMissing or CardsNotVisible | Seat permission not delegated or cards\_visible guard tripped | Verify all per-seat Permission PDAs are delegated                                               |
| `6100`                   | SeatsNotInitialized                           | A seat is still delegating at start\_game time                | Wait and re-read until all accounts ready                                                       |
| `6126`                   | WaitingTableExists                            | Stale waiting bitmap from a prior SNG match                   | Ask in the Discord operator/dealer-license support section with the pool and table identifiers  |
| `6152`                   | EmissionAccountsRequired                      | Governed emission accounts were omitted                       | Pass global `EmissionCtrl` and the matching `(game_type,tier)` `PoolIdle`                       |
| `6153`                   | InvalidEmissionAccount                        | Wrong owner/PDA/cell or malformed emission account            | Re-derive both PDAs and verify the PoolIdle cell bytes                                          |
| `6184` / `6185`          | SngDuelStateRequired / InvalidSngDuelState    | 6/9-max sidecar missing or invalid                            | Initialize/repair the canonical table sidecar; do not downgrade to legacy payout                |
| `6189` / `6190`          | SngDuelInactive / SngDuelAlreadyActive        | Duel lane raced current state                                 | Re-read the sidecar and choose start/action/resolve from live state                             |
| `6192`                   | SngDuelTimeoutNotReady                        | Duel deadline has not passed                                  | Wait for the on-chain 20-second deadline; do not busy-loop                                      |
| `6193`                   | TableNotClean                                 | One or more reuse gates still fail                            | Inspect record payment, active duel, jackpot entries, rewards, seats, and setup state           |
| `6194`-`6197`            | Settlement record guards                      | Missing/stale/unfinalized/already-paid record                 | Follow the record state machine; never fall back to unrecorded distribution                     |
| `500`                    | TEE proxy error                               | Various, often auth-related                                   | Check TEE token freshness; check delegation status                                              |
| `403`                    | TEE access denied                             | Signer not in the account's permission members                | Don't reference private accounts unless signer is permitted                                     |

## Common symptoms

### "Blockhash not found" cascades after \~50 minutes

**Cause:** TEE auth token rotated and a retry helper captured a stale resolver.

**Fix:** The Dealer Service refreshes TEE auth through the current resolver path. Restart the dealer if the heartbeat shows repeated proxy errors after token rotation.

### Dealer keeps double-sending the same TX

**Cause:** Two dealer instances are processing the same table set without running as a coordinated fleet.

**Fix:** Check for stale processes. Run the instances as a fleet (shared shard map + stand-down guard), or give each a disjoint `table_whitelist` / SNG pool filter when you run multiple dealers.

```bash
pgrep -af 'dealer (start|run)'
cat data/.crank.pid
```

### Cashout pending for more than 5 minutes

**Cause:** Usually L1 RPC congestion or a TEE token rotation mid-pipeline.

**Fix:** The dealer retries automatically. If the cashout is still pending after 10 minutes, check the heartbeat for `recentErrors`. If you see `InvalidWritableAccount` repeatedly, ask in the Discord operator/dealer-license support section with the table and seat identifiers.

### `process_cashout_v2` succeeds but `clear_leaving_seat` fails repeatedly

**Cause:** Receipt nonce proof mismatch. The L1 cashout produced a nonce that the TEE seat does not recognize.

**Fix:** Confirm the TEE has the committed seat data. The dealer's `commit_state` step must finalize on L1 before `process_cashout_v2` runs.

### MagicBlock CAU silently fails for 10+ accounts

**Cause:** MagicBlock CAU bundles can fail when too many accounts are packed into one bundle.

**Fix:** Chunk to at most 4 seats per CAU. Don't retry; poll L1 to confirm what actually landed.

### Dealer starts but tracks 0 tables

**Cause:** `table_filter_mode` set to `whitelist` with an empty `table_whitelist`, or the dealer is missing L1 RPC access.

**Fix:** Check `data/crank-config.json`. Verify RPC reachability with `solana cluster-version --url <your-rpc>`.

### "insufficient account keys" warning at startup

**Cause:** Funder auto-refill subsystem cannot simulate its setup TX. Non-blocking; the dealer runs fine.

**Fix:** Keep the dealer wallet funded manually if auto-refill is unavailable.

### `SeatsNotInitialized` (6100) on `start_game`

**Cause:** A seat is still in the middle of being delegated when the dealer submits `start_game`.

**Fix:** The dealer should wait until every expected seat, seat\_cards, and permission account is in TEE-owned state before submitting. If this repeats, check RPC health and setup logs for the slow account before restarting the dealer.

### SNG cannot reset after player balances were credited

**Cause:** Player payout and table reuse are separate gates. A paid settlement record does not mean jackpot entries, reward epoch state, duel state, or seats are clean.

**Fix:** Read the current record and sidecar, finish jackpot-entry closure and reward finalization, then run `assert_table_clean`. Repair only the named gap. Close `SngSettlementRecord` after a successful reset, not before.

### SNG payout is visible in the record but not in the wallet

**Cause:** `distribute_prizes_from_record` credits claimable state. It does not promise a direct wallet transfer.

**Fix:** Verify the record is `paid`, then compare its per-game delta with the Player account's cumulative `claimable_sol` and the Steel unrefined balance. The player separately signs the SOL claim and Claim All/refinement flow.

## Restarting the dealer

The dealer is designed to be safely restartable: L1 is the source of truth, and the next discovery sweep re-adopts every active table. If:

* `recentErrors` is the same error 10+ times in a row, OR
* `tablesProcessing` is non-zero for > 5 minutes with no new metrics lines, OR
* A specific table is making no progress despite no errors,

restart the dealer:

```bash
printf '{"action":"restart"}\n' > data/crank-control.json
```

For a managed service:

```bash
./dealer service restart
```

Re-adoption usually adds about 30 seconds of latency.

## Escalation

For operator-sensitive scenarios, use the Discord operator/dealer-license support section. Do not post private keys, seed phrases, or unreleased incident details in public chat.
