Platform
ScaiWave ScaiGrid ScaiCore ScaiBot ScaiDrive ScaiKey Models Tools & Services
Solutions
Organisations Developers Internet Service Providers Managed Service Providers AI-in-a-Box
Resources
Support Documentation Blog Downloads
Company
About Research Careers Investment Opportunities Contact
Log in

Troubleshooting

Common failure modes and the fastest way to diagnose them. Symptoms in bold; likely causes and fixes underneath.

Mail is accepted (202) but never delivers#

Symptoms: /v3/mail/send returns 202, but the message sits in QUEUED or PROCESSING forever. No events arrive.

Check:

  1. Worker service alive? systemctl status scaisend-worker or the equivalent. Restart if dead.
  2. Redis reachable? redis-cli ping.
  3. Queue depth. redis-cli LLEN email:process. If non-zero and growing, workers aren't keeping up (scale) or are deadlocked (restart).
  4. Worker logs. Look for render_error, database_error, or stack traces.

Most common fix: the Worker service died silently. The API still accepts; nothing consumes. Restart.

Messages stay in PROCESSING indefinitely#

Symptoms: Messages enter PROCESSING but never progress to RENDERED or SENDING.

Check:

  1. Template errors. GET /v3/messages/{id} — check error_message. If it's a template render failure, fix the template or delete the offending send.
  2. Worker crash mid-render. The worker was handling the job, died, and the job record stayed in PROCESSING. Use POST /v3/messages/{id}/retry to requeue.

All sends failing with 403 "Sender domain not verified"#

Symptoms: Every POST /v3/mail/send returns 403 with "Sender domain not verified" even though you previously verified.

Check:

  1. Is the DNS still published? Query scaisend._domainkey.<yourdomain> — does it resolve?
  2. Did someone rotate DKIM and not re-verify? Check GET /api/admin/domains/{id}. If verified: false, run POST /api/admin/domains/{id}/verify.
  3. Did a PATCH set is_active: false? Re-activate.

Bounces climbing above 2%#

Symptoms: GET /v3/stats/sum shows bounces / requests > 0.02.

Check:

  1. Sample recent bounces. GET /v3/suppression/bounces?limit=50&start_time=<1h ago>. Look at reason:
    • Mostly 5.1.1 User unknown → list quality problem. Your list has many invalid addresses.
    • Mostly 5.7.* → reputation problem. ISPs are rejecting you.
    • Mostly 5.7.26 DMARC failure → authentication misconfig. Run POST /api/admin/domains/{id}/verify and fix any failures.
  2. Check recent signup flows. Was there a spike of obvious garbage addresses? Bot signups, typos?
  3. If reputation-driven, cool down sends. Slow marketing sends; prioritize transactional (which ISPs evaluate separately, usually more charitably). Give yourself a week before sending the next big batch.

Spam report rate > 0.1%#

Symptoms: Recipients are hitting "Report spam" in large numbers.

Check:

  1. Recent campaigns. Was there a send to a list that might not have been opt-in? An imported list that's older than 6 months? A broad-reach campaign that hit dormant users?
  2. Unsubscribe flow. Is it obvious? Is the List-Unsubscribe header present (you can see it in any received message via "Show original")? Is one-click working?
  3. Suspend the offending campaign. Cancel remaining queued messages in the batch (POST /v3/messages/{id}/cancel for each).

Webhook endpoint gets disabled#

Symptoms: GET /v3/user/webhooks/{id} shows disabled_at set.

Check:

  1. Endpoint returning 2xx? Test with curl -X POST <url> -d '{}' to confirm it answers. 404s from typos are the most common cause.
  2. Endpoint too slow? 30-second timeout. If your handler takes more than ~10s on average, you're flirting with timeouts during retries.
  3. TLS valid? Certificate expired, mismatched hostname, self-signed cert that ScaiSend won't accept.
  4. DNS change? Your endpoint hostname moved and the old IP stopped answering.

Fix the cause, then PATCH /v3/user/webhooks/{id} with {"enabled": true}.

Outbound mail rejected by all recipients#

Symptoms: Every message bounces with varied reputation-related 5.7.* codes.

Check:

  1. PTR records on your outbound IPs. dig -x <IP> — does it resolve? Is the resolved name's forward record the same IP (FCrDNS)? If not, fix with your IP provider. This is the #1 cause of mysterious reputation drops.
  2. RBL listings. Check your outbound IPs against Spamhaus, SpamCop, Barracuda. MXToolbox Blacklists is a quick survey.
  3. Rapid volume ramp-up. If you went from 0 to 100k/day overnight, ISPs flag that as suspicious. Warm up IPs with gradually increasing volume.
  4. Content issues. Some content patterns (excessive links, spammy phrases, bare IPs) tank deliverability. Test a sample message through mail-tester.com.

"Missing required scope" on unexpected endpoints#

Symptoms: Getting 403 with Missing required scope: X on an endpoint that previously worked.

Check:

  1. Did someone rotate the API key? If the new key was created with a smaller scope set, it can't do what the old key could. Check GET /v3/api_keys/{id}.
  2. Did admin change role permissions? User roles are editable. A permission may have been removed from the user's role.
  3. Is the user part of the expected group? If group-to-role mapping is your primary RBAC mechanism, a group membership change in ScaiKey might have removed the permission.

GET /v3/auth/me shows the caller's effective permissions. Compare against what the endpoint needs.

DNS verification stuck at verified: false#

Symptoms: POST /api/admin/domains/{id}/verify keeps returning verified: false even though you believe the records are published.

Check:

  1. Wait for DNS TTL. DNS propagates at the pace of the slowest cache in the chain. Even a "small TTL" provider takes minutes. Try again in 10 minutes.
  2. Query DNS the same way ScaiSend does. dig scaisend._domainkey.<domain> TXT. Compare the returned value against what GET /api/admin/domains/{id}/dns-records tells you to publish. Look for:
    • Trailing or leading whitespace in the DNS value. Some providers strip or pad.
    • Line breaks. Long TXT records may be split across multiple DNS strings; ScaiSend joins them, but some DNS servers concatenate with spaces. Check the raw query result.
    • Wrong base64. Copy-paste errors are common; check a few characters from the beginning and end.
  3. Multiple TXT records. If you have an existing SPF record, adding a second TXT can cause verification to see the wrong one. Merge SPF records into a single v=spf1 ... entry.

Inbound SMTP server not receiving DSNs#

Symptoms: Messages sometimes bounce silently — the upstream MX accepts but the message never delivers, and no bounce event appears in ScaiSend.

Check:

  1. Port 25 reachable from the internet? telnet <your-smtp-host> 25 from outside your network. If it refuses, check firewall rules.
  2. Forward-confirmed reverse DNS. dig -x <inbound-ip> should return your hostname; dig <hostname> should return the same IP.
  3. SMTP service running? systemctl status scaisend-smtp.
  4. Correct envelope sender on outbound messages? ScaiSend puts a distinctive envelope-from that routes bounces back to its inbound server. If you've overridden this somehow, bounces go elsewhere.

Admin UI can't log in#

Symptoms: OAuth redirect lands on an error page.

Check:

  1. ScaiKey reachable from the browser? The admin UI initiates OAuth against ScaiKey's URL; the browser must be able to reach it.
  2. ADMIN_URL correctly configured? The redirect URI registered with ScaiKey must match ADMIN_URL exactly. Mismatch → "invalid redirect_uri" from ScaiKey.
  3. JWKS endpoint reachable from ScaiSend? ScaiSend fetches JWKs at JWT validation. A blocked egress to ScaiKey means no login works server-side.

Statistics look wrong#

Symptoms: /v3/stats counts don't match what you think happened.

Check:

  1. Stats are aggregated on a daily-batch basis. The current day may not be fully reflected until the next rebuild. For up-to-the-minute numbers, query /v3/messages directly and count.
  2. Sandbox messages don't count. If you've been testing with a test key, those messages are excluded from stats.
  3. Rebuild if suspicious. POST /v3/stats/rebuild replays events from source. Requires stats.export.

Redis queue growing without bound#

Symptoms: redis-cli LLEN smtp:deliver climbs monotonically.

Check:

  1. SMTP service alive? If the consumer is dead, the queue fills.
  2. Outbound IP blocked? If every send is being refused at the network layer (firewall, ISP blocking port 25), the SMTP service loops retrying without making progress. Check logs for connection-refused patterns.
  3. Rate-limited by a specific recipient ISP? One domain's MX saying "slow down" can back up the queue if you have a lot of mail to that domain. Check retry counts — if one domain dominates, you're seeing a reputation issue with that specific ISP.

Temporarily drain by increasing SMTP service replicas. Long-term fix depends on the root cause.

Still stuck?#

  • Request IDs. Every API response carries X-Request-ID. Include it when filing a support ticket.
  • Message IDs. For delivery issues, the message_id from the send response is the key identifier. Pair it with the request ID.
  • Log context. Ship structured logs to a searchable store so grep request_id=... across all three services is possible.
Updated 2026-05-17 01:33:27 View source (.md) rev 1