● Help · Errors
Troubleshooting
every error code, and the fix.
API errors come back as JSON {"error": "<code>", "details"?: …}. Every code below was taken from apps/api/src and packages/airdrop/src. Common setup problems come first.
01Common setup problems
| Symptom | Cause and fix |
|---|---|
| API stops with Invalid environment configuration | It lists each bad variable, e.g. ENCRYPTION_KEY: must be 64 hex characters, ADMIN_PUBLIC_URL must be a full URL like https://admin.example.com or BROADCAST_WORKER must be true or false. Fix .env (see Configuration). |
| Webhook skipped — the API URL is not https | PUBLIC_API_URL is not https. Put the API behind TLS, set it, restart, save the bot token again. |
The bot does not answer /start, Stars payments never arrive | No webhook (see above), or the API is unreachable from the internet. |
| Mini App shows Open in Telegram | Opened outside Telegram without a signed login. Use the bot, or pnpm dev:initdata <slug> locally. |
| Tracked link or squad invite opens nothing or the wrong campaign | Main Mini App not set in BotFather, or its URL lacks ?c=<slug>. |
| Admin login loops back to the sign-in form | Admin and API are on different registrable domains, so the SameSite=Lax cookie is not sent. Use admin.example.com + api.example.com. |
Admin saves fail with forbidden_origin | Admin origin missing from CORS_ORIGINS. |
| Browser console shows a CSP error for the API | The app was built with another VITE_API_URL/VITE_ADMIN_API_URL. Rebuild. |
| Wallet connect fails | VITE_PUBLIC_URL / VITE_ADMIN_PUBLIC_URL missing so the manifest points at localhost. Rebuild and open the manifest URL to check. |
| Client report link opens the Mini App or a 404 | Set ADMIN_PUBLIC_URL on the API and the index.html fallback on the admin host. |
| Admin page reload shows 404 | Missing SPA fallback on the static host (_redirects on Netlify, try_files in nginx/Caddy). |
| Wallet checks skipped on Anti-bot | No TONCENTER_API_KEY. Optional. |
| Puzzles all fail after a server move | ABUSE_HASH_SALT changed; stored answers are salted with the old value. Restore it or reschedule puzzles. |
| Bot tokens cannot be decrypted after a restore | ENCRYPTION_KEY differs. Restore the original .env or paste every bot token again. |
| Broadcasts stay in "sending" | BROADCAST_WORKER=false on the only API process, or the API is down. Check docker compose logs api. |
02Error codes: Sign-in and setup
| Code | HTTP | Meaning | What to do |
|---|---|---|---|
unauthorized | 401 | Player login missing or invalid, or admin not signed in. | Open the Mini App from Telegram (or use pnpm dev:initdata locally); sign in again in the admin. |
invalid_credentials | 401 | Wrong admin e-mail or password. | Check both; after 10 tries the login is slowed to 1 per 6 s. |
init_data_stale | 401 | Re-verification needs a Telegram login at most 10 minutes old. | Close and reopen the Mini App, then re-verify. |
forbidden | 403 | Your role may not do this. | Ask an owner (see roles). |
forbidden_origin | 403 | Admin change from an origin not in CORS_ORIGINS. | Add the exact admin origin to CORS_ORIGINS and restart the API. |
setup_already_done | 409 | An admin already exists. | Sign in; ask the owner for an account. |
email_taken | 409 | That e-mail already has an admin account. | Use another e-mail. |
last_owner | 409 | The last active owner cannot be demoted, deactivated or removed. | Make another admin owner first. |
cannot_delete_self | 409 | You cannot remove your own account. | Ask another owner. |
rate_limited | 429 | Too many requests. | Wait a moment. Behind a proxy, check TRUST_PROXY=true and X-Forwarded-For, or everyone shares one IP. |
03Error codes: Campaign and bot
| Code | HTTP | Meaning | What to do |
|---|---|---|---|
campaign_not_found | 404 | Unknown slug. | Check ?c=<slug> in the Mini App URL and in the BotFather Main Mini App URL. |
bot_not_configured | 409 / 503 | The campaign has no bot token. | Connect the bot in Settings → Launch. |
invalid_bot_token | 400 | Telegram rejected the token. | Copy it again from @BotFather (/token). |
bot_in_use_by_another_campaign | 409 | The bot serves another campaign. | Create a new bot. |
slug_taken | 409 | Slug already used. | Choose another slug. |
campaign_not_active | 409 | The game only accepts actions in draft or live. | Resume the campaign; after publish, earning has stopped by design. |
banned | 403 | The player is banned. | Unban in Players if it was a mistake. |
telegram_error | 502 | Telegram refused an admin action (for example a refund). | Read details.description. |
payload_too_large | 413 | Request body too large. | Send less data. |
04Error codes: Game, quests, shop
| Code | HTTP | Meaning | What to do |
|---|---|---|---|
insufficient_points / max_level / locked / upgrade_not_found | 409 | Upgrade not affordable, at max level, or its required card level is missing. | Normal game feedback. |
already_claimed | 409 | Daily reward or pass tier already claimed. | Normal game feedback. |
quest_not_found / quest_unavailable | 404 / 409 | Quest removed, inactive, out of its dates or its sponsor budget is spent. | Check the quest in the admin. |
verification_unavailable | 502 | The bot cannot read the channel. | Make the bot an admin of the channel or group. |
quest_misconfigured | 500 | A channel quest has no chat id. | Edit the quest. |
item_not_found / item_inactive / already_owned / not_owned | 404 / 409 / 403 | Shop item missing, hidden, already bought, or not owned when equipping. | Normal shop feedback. |
payment_unavailable | 502 | Telegram could not create the Stars invoice. | Check the bot token and Telegram status; retry. |
already_refunded / purchase_not_found | 409 / 404 | Refund already done or unknown purchase. | Nothing to do. |
05Error codes: Rewarded ads
| Code | HTTP | Meaning | What to do |
|---|---|---|---|
ads_disabled | 409 | Ads are off for the campaign. | Enable them in Economy. |
ads_not_configured | 409 | Server confirmation required but no Reward URL generated. | Generate the Reward URL first. |
too_early | 409 | Ad completed faster than 10 s (also used for link quests before the minimum time). | Watch the whole ad. |
daily_cap_reached | 409 | Daily ad cap reached. | Normal; resets next UTC day. |
server_confirm_required | 409 | Only Adsgram's callback grants the reward. | The Mini App waits for it automatically. |
intent_not_found / intent_expired / intent_used / no_pending_intent / too_many_pending_intents | 404 / 409 / 429 | The ad view was not started, expired, already rewarded, or too many open. | Start a new ad. |
06Error codes: Wallet
| Code | HTTP | Meaning | What to do |
|---|---|---|---|
invalid_proof | 400 | TON Connect proof invalid (details.reason). | Check VITE_PUBLIC_URL and the manifest; the proof domain must be the Mini App host, a CORS_ORIGINS host or in TON_PROOF_DOMAINS. |
wallet_linked_to_another_player | 409 | One wallet per player. | Use another wallet. |
snapshot_published | 409 | Wallets are frozen after publish. | By design. |
07Error codes: Seasons, events, squads, puzzles
| Code | HTTP | Meaning | What to do |
|---|---|---|---|
season_overlap / season_number_conflict | 409 | Season dates overlap another season. | Change the dates. |
season_started / season_has_progress | 409 | Start date and points-per-XP are fixed once started; seasons with progress cannot be deleted. | Create a new season instead. |
no_active_season / tier_not_reached / nothing_to_claim / reward_unavailable | 409 | Nothing to claim right now, or the cosmetic reward item is gone. | Check the tiers in the builder. |
premium_pass_required / no_premium_track | 403 / 409 | Premium track needs the pass; or the season has no pass price. | Normal. |
event_overlap / event_started / event_ended | 409 | Same-kind events overlap, or the event is running or over. | End it early or schedule another. |
already_in_squad / already_member / squad_full / squad_closed / name_taken / not_owner / not_in_squad / not_a_member / cannot_kick_self | 400–409 | Squad rules: one squad per player, max 100 members, invite-only squads need a code, unique names, owner-only actions. | Normal squad feedback. |
no_puzzle_today / no_attempts_left / already_solved | 404 / 429 / 409 | No puzzle scheduled, 5 attempts used, or already solved. | Schedule puzzles ahead. |
puzzle_exists / puzzle_not_future | 409 | One puzzle per day; only future puzzles can be removed. | Pick another day. |
share_unavailable / achievement_locked | 502 / 409 | Telegram refused the prepared message, or the achievement is not unlocked. | Retry later. |
08Error codes: Fairness and appeals
| Code | HTTP | Meaning | What to do |
|---|---|---|---|
reverification_closed | 409 | No re-verification window open, or a snapshot is published. | Open a window in Fairness. |
appeals_closed / appeal_already_open / nothing_to_appeal / appeal_closed | 409 | Appeals off, one already open, player is eligible, or already decided. | Normal. |
rules_unchanged | 409 | Publishing rules identical to the current version. | Edit the rules first. |
09Error codes: Growth, reports, sponsors
| Code | HTTP | Meaning | What to do |
|---|---|---|---|
code_taken | 409 | Tracked link code already used. | Choose another code or leave it empty. |
segment_empty | 409 | The broadcast audience is empty. | Pick another segment. |
mini_app_url_required | 409 | Broadcast button needs an https Mini App URL. | Set it in Launch, or remove the button. |
broadcast_not_draft / broadcast_not_cancellable | 409 | Broadcast already sent or finished. | Create a new one. |
report_revoked / report_expired | 410 | Client report link no longer valid. | Create a new link. |
report_not_found | 404 | Wrong report token. | Check the link; wrong tokens are rate-limited. |
sponsor_has_quests | 409 | Sponsor still has quests. | Delete or unlink its quests first. |
10Error codes: Airdrop
| Code | HTTP | Meaning | What to do |
|---|---|---|---|
jetton_master_not_configured | 422 | No jetton master on the Token page. | Add it. |
snapshot_empty | 422 | Nobody is eligible. | Check wallets linked and the minimum points. |
invalid_tier_amount / total_amount_must_be_positive | 422 | Bad draft input. | Fix the total or tiers. |
snapshot_already_published / snapshot_published_immutable | 409 | Published snapshots cannot change. | By design. |
merkle_proof_invalid / merkle_entry_mismatch / duplicate_address | 409 / 422 | Tree check failed at publish. | Recompute the draft; report the case to support. |
invalid_claim_deadline / invalid_network / invalid_owner_address / invalid_address | 422 | Bad deploy parameters. | Deadline in the future, network matching the wallet, valid addresses. |
distributor_mismatch | 422 | Address differs from the contract built from this snapshot, deadline, jetton master, owner and network. | Do not fund that address; prepare the deploy again. |
owner_jetton_wallet_required / owner_jetton_wallet_lookup_failed / invalid_owner_jetton_wallet | 422 / 502 | Your jetton wallet for the fund transfer is missing or could not be looked up. | Paste it, or set TONCENTER_API_KEY. |
distributor_not_set / snapshot_not_published / not_published | 409 / 404 | Step done out of order. | Follow the runbook order. |
11FAQ
Can players buy points or boosts with Stars?
No. Stars buy cosmetics only; the API refuses anything else.
Can one install run several clients?
Yes, one bot and campaign per client. Admins see all campaigns; give clients report links, not admin accounts.
Does MIKODES take a share or run a server?
No. You host everything and keep all revenue.
Do I need a toncenter key?
No. Without it two wallet anti-bot signals are skipped, and the admin reads on-chain status through toncenter's public API from your browser.
Mainnet?
Set TON_NETWORK=mainnet only after a full testnet run and an independent contract audit.
Which licence do I need to sell campaigns to clients?
Check the licence terms of the marketplace or agreement you bought under. This documentation is not legal advice.