Troubleshooting
Common issues and how to resolve them.
Notifications not arriving
Check the delivery logs
The most common starting point. Go to Webhooks → (your webhook) → Delivery Logs in the dashboard. Each notification shows its delivery status for every channel.
queued— Still processing. Wait a moment and refresh.delivered— Alphorn sent it successfully. The issue is on the channel side (check Slack/Discord/Email).retrying— Delivery failed and Alphorn is retrying. Check the error message for details.failed— All retries exhausted. The error message tells you what went wrong.
Verify your webhook URL
Make sure your webhook URL is correct and accessible:
curl -s -X POST https://app.alphorn.dev/api/webhooks/wh_abc123 \
-H "Content-Type: application/json" \
-d '{"title": "Test", "message": "Testing webhook"}'You should get back:
{"id": "msg_abc123", "status": "queued"}If you get a 404, the webhook ID is wrong. If you get no response, check your network connectivity.
Check filtering rules
If a channel isn't receiving notifications, it might be filtered out. Go to Channels → (your channel) and check the filtering rules. A notification must match all rules to be delivered. Try temporarily removing filters to confirm.
Channel configuration issues
Common mistakes by channel type:
| Channel | Common issue |
|---|---|
| Slack | Webhook URL expired or was regenerated — get a new one from Slack |
| Discord | Webhook URL deleted — recreate in Discord channel settings |
| Email (SMTP) | Wrong port, missing TLS, or credentials rejected by provider |
| Telegram | Bot not added to chat, or wrong chat ID (group IDs are negative numbers) |
| PagerDuty | Wrong integration key — use the Events API v2 integration key, not the API key |
| Microsoft Teams | Incoming Webhook connector disabled or removed from channel |
Self-hosting issues
Database connection errors
Symptom: Alphorn won't start, logs show connection errors.
Check your DATABASE_URL:
postgres://user:password@host:5432/dbname- Is PostgreSQL running and accepting connections?
- Is the hostname correct? Inside Docker Compose, use the service name (e.g.,
db), notlocalhost. - Is the port correct? Default is 5432.
- Do the credentials match your PostgreSQL configuration?
Migrations fail on startup
Alphorn runs database migrations automatically. If they fail:
- Check that the database user has permission to create tables and alter schema
- Check PostgreSQL logs for specific error messages
- Make sure you're running PostgreSQL 14+
Alphorn starts but isn't accessible
- Check that port 3000 is mapped correctly in your Docker Compose or firewall
- If behind a reverse proxy, make sure the proxy passes requests to port 3000
- Verify
BETTER_AUTH_URLmatches the URL you're accessing Alphorn from
SSO / OAuth not working
- Verify the callback URL matches exactly:
{BETTER_AUTH_URL}/api/auth/callback/{provider} - Check that
BETTER_AUTH_URLincludes the protocol (https://) and has no trailing slash - For OIDC providers, verify the discovery URL returns a valid configuration
- Check provider-specific setup in Self-Hosting → SSO / OAuth
API issues
HTTP 400 — Invalid payload
Your request body is malformed. Common causes:
- Missing
messagefield (the only required field) - Invalid JSON syntax (trailing commas, unquoted keys)
- Wrong
Content-Typeheader — useapplication/jsonfor JSON payloads
HTTP 404 — Webhook not found
The webhook ID in your URL doesn't exist. Check for typos. If you recently deleted and recreated a webhook, the URL changed.
HTTP 429 — Rate limit exceeded
You've hit your plan's monthly message limit. Check your usage in Settings → Billing. Options:
- Upgrade your plan
- Reduce notification volume with more selective filtering
- Wait for the next billing cycle
Streaming issues
SSE connection drops
Server-Sent Events connections may drop due to network issues, proxy timeouts, or server restarts. Your client should reconnect automatically:
const eventSource = new EventSource(
"https://app.alphorn.dev/api/stream/wh_abc123"
);
eventSource.onerror = () => {
// EventSource reconnects automatically
// Implement backoff if you need custom reconnection logic
console.log("Connection lost, reconnecting...");
};If connections drop frequently behind a reverse proxy, increase the proxy timeout:
# Nginx
proxy_read_timeout 86400;
proxy_buffering off;