Skip to content

Troubleshooting

Connection and pairing

SymptomLikely causeFix
GET /qr returns 409 QR_NOT_AVAILABLE right after connectPairing is starting (1–2 s)Retry after a second; check status
Status stays CONNECTINGNo worker owns the instance (worker down or at WORKER_MAX_SESSIONS)Check worker health and whatstig_worker_sessions_active; add a worker
DISCONNECTED with QR_TIMEOUTQR not scanned within ~3 minCall connect again and scan promptly
Phone says "couldn't link device"Phone offline, old WhatsApp version, too many linked devices (max 4)Update WhatsApp, remove an old linked device, retry
LOGGED_OUT / LOGGED_OUT_FROM_PHONEDevice removed on the phone, or WhatsApp invalidated the sessionRelink with connect
LOGGED_OUT / BAD_SESSIONStored session unusable (e.g. after restoring an old backup)Relink
DISCONNECTED / CONNECTION_REPLACEDThe same session was opened elsewhere (another tool using the same credentials)Stop the other client, then reconnect
RESTRICTEDWhatsApp banned/restricted the numberCannot be fixed by WhatsTIG; appeal in the WhatsApp app; review sending practices
RECONNECTING / RECONNECT_EXHAUSTED12 fast reconnects failed (network or WhatsApp outage); the worker keeps retrying every ~5 minNothing: it reconnects by itself when the outage ends. Call reconnect to retry immediately
Instances reconnect after each deployExpected: deploys restart sockets (no QR needed)—
Many whatstig_session_lease_lost_totalWorker overloaded (event-loop lag) or database latency causing missed heartbeatsAdd workers, check DB, consider a larger LEASE_TTL_MS

Sending

SymptomLikely causeFix
Messages stay QUEUEDInstance not CONNECTED, or pacing limit (default 20/min per instance)Check instance status; tune INSTANCE_MESSAGES_PER_MINUTE or the instance's rate_policy
FAILED / EXPIREDInstance was disconnected longer than the message TTLReconnect; use appropriate expiresInSeconds
FAILED / RECIPIENT_NOT_ON_WHATSAPPNumber has no WhatsAppCorrect the number / use another channel
400 INVALID_RECIPIENTNumber not valid in international formatInclude the country code or set the project's default country
UNKNOWNWorker stopped mid-send, or an unexpected provider errorSee reliability guide; check worker logs for the message ID
Stays SENT, never DELIVEREDRecipient offline, or blocked/has no receipts; or the number blocked youNothing to fix; receipts are not guaranteed
429 BACKLOG_LIMIT_REACHEDToo many queued messages in the projectSlow down producers; check why the instance is not sending
409 IDEMPOTENCY_KEY_REUSEDSame key used for different contentUse a unique key per logical message

Webhooks

SymptomFix
Deliveries failed with UnsafeUrlErrorURL resolves to a private address or is not HTTPS — use a public HTTPS URL
Signature mismatchVerify against the raw body (no re-serialization), correct secret (rotated?), clock in sync (±5 min)
Endpoint disabled100 consecutive failures — fix the endpoint, PATCH { "enabled": true }, replay dead deliveries
DuplicatesExpected (at-least-once): deduplicate on event id
Out-of-order eventsExpected: use occurredAt and status rank

Dashboard and auth

SymptomFix
No verification emailCheck SMTP_URL and the API logs ("SMTP_URL not configured" means emails are only logged)
403 CSRF_REJECTEDThe dashboard origin is not PUBLIC_APP_URL/TRUSTED_ORIGINS, or a proxy strips the Origin header
Signed out repeatedlyBETTER_AUTH_SECRET differs between API replicas, or cookies blocked because PUBLIC_APP_URL scheme mismatches

Platform

SymptomFix
Service exits with "Invalid configuration"The listed variables are missing/invalid; compare with .env.example
Decryption failed in worker logsWHATSTIG_ENCRYPTION_KEYS missing the key version used for stored data — restore the key
API 503 on readinessPostgreSQL or Redis unreachable
High event-loop lag on a workerToo many sessions for one process — add workers / lower WORKER_MAX_SESSIONS

When reporting an issue, include the requestId (API responses), instance ID, message ID and approximate time.