Troubleshooting
Diagnosis and recovery guide organized by subsystem. Start with the failing area, check the common causes, and apply the fix.
Event resolution
| Symptom | Cause | Fix |
|---|---|---|
| Event not loading on subdomain | Missing domain entry | Add hostname to platform_event_domains table |
| Wrong event loading | Duplicate hostname | Check platform_event_domains for conflicts |
| Event works locally but not in production | DNS not propagated | Wait for DNS propagation; verify CNAME/A records |
| 503 "Event is temporarily unavailable" | Event is suspended | Change event status in platform UI |
| 503 "Event is in read-only mode" | Post-event or archived mode | Change event mode in admin settings or platform UI |
Key files: hooks.server.ts, resolve-event.ts
Authentication
| Symptom | Cause | Fix |
|---|---|---|
| No OTP email received | Mailgun misconfigured | Verify MAILGUN_API_KEY and MAILGUN_DOMAIN |
| No OTP email received | Email not in allowed list | Add email to allowed list or approve access request |
| No OTP email received | Spam filter | Check spam/junk folder |
| OTP code invalid | Code expired (10 min TTL) | Request a new code |
| OTP code invalid | Too many attempts (max 3) | Request a new code |
| OTP rate limited | Too many generations (5 per 10 min) | Wait 10 minutes |
| Session lost after server restart | In-memory KV (Node runtime) | Expected behavior locally; re-authenticate |
| Logged out unexpectedly | Session generation incremented | Re-authenticate; someone called invalidateUserSessions |
Key files: auth.ts, hooks.server.ts
Admin access
| Symptom | Cause | Fix |
|---|---|---|
Redirected from /admin | Not signed in | Sign in at /auth |
Redirected from /admin | Email not in admin list | Add email to adminEmails in settings |
| Admin sees empty data | Wrong event resolved | Verify hostname matches correct event |
Platform /platform access denied | Not an operator | Add email to PLATFORM_OPERATOR_EMAILS or platform_users |
Key files: hooks.server.ts, settings.ts, platform/auth.ts
Payments
| Symptom | Cause | Fix |
|---|---|---|
| Checkout doesn't open | Stripe key missing or invalid | Verify STRIPE_SECRET_KEY |
| Payment shows pending after completion | Webhook not delivered | Check Stripe webhook delivery dashboard |
| Webhook returns 400 | Wrong signing secret | Verify STRIPE_WEBHOOK_SECRET matches endpoint |
| Wrong payment total | Tier multiplier incorrect | Check pricing tier multipliers and explicit tier prices |
| Wrong payment total | Add-on amount wrong | Check add-on amountCents value |
| Refund fails | Payment intent in wrong state | Check Stripe dashboard for payment intent status |
| PayPal not working | Missing PayPal credentials | Set paypalClientId, paypalClientSecret in settings |
Key files: api/stripe/checkout, api/stripe/webhook, stripe.ts
Email
| Symptom | Cause | Fix |
|---|---|---|
| No emails sending | Mailgun credentials wrong | Verify MAILGUN_API_KEY and MAILGUN_DOMAIN |
| Emails going to spam | SPF/DKIM not configured | Set up SPF and DKIM records for the sending domain |
| Announcement send failed | Check error message | Review the error in the announcement record |
| Wrong sender address | Email settings not set | Configure emailFrom in event settings |
Photos and documents
| Symptom | Cause | Fix |
|---|---|---|
| Upload fails | File too large (max 10 MB) | Reduce file size |
| Upload fails | R2 binding misconfigured | Verify R2 bucket exists and is bound |
| Photo not displaying | Auth proxy issue | Check session and API route |
| Document access denied | Permission mismatch | Verify email/group permissions on the document |
| Files lost after restart (Docker) | No volume mount | Mount data volume: -v $(pwd)/data:/app/data |
Key files: api/photos/, api/documents/, runtime/types.ts
Database
| Symptom | Cause | Fix |
|---|---|---|
| Migration fails locally | Schema syntax error | Check schema.ts for issues; run npm run db:generate |
| Migration fails remotely | D1 constraints | Verify new columns have defaults or are nullable |
| Data leaking across events | Missing event_id filter | Add eq(table.eventId, eventId) to all queries |
| Stale data showing | Settings cache | Wait 5 seconds (cache TTL) or restart server |
Deployment
| Symptom | Cause | Fix |
|---|---|---|
| CI deploy fails | Invalid API token | Verify CF_DEPLOY_API_TOKEN permissions |
| CI deploy fails | Wrong account ID | Check CF_ACCOUNT_ID matches target account |
| Missing bindings after deploy | Resource IDs wrong | Verify D1_DATABASE_ID, KV_NAMESPACE_ID, R2_BUCKET_NAME |
| Docs not updating | Wrong docs worker name | Check DOCS_WORKER_NAME in environment |
Key files: .github/workflows/apps-ci.yml, wrangler.toml
Diagnostic steps
When none of the above match:
- Identify the subsystem: Platform UI, event resolution, auth, payment, or storage
- Reproduce: Note the exact route, action, and error message
- Check environment: Verify env vars and secrets are set correctly
- Check logs: Cloudflare Workers dashboard or local console output
- Check database: Inspect records directly (local SQLite or D1 console)
- Re-run the flow: After applying fix, test the full end-to-end path
Related pages
- Routes & APIs — route mapping for identifying failing endpoints
- Environment Variables — check required configuration
- Architecture — understand the request lifecycle