Troubleshooting
Common issues with Hogsend and how to fix them -- events, journeys, emails, Hatchet, database, Redis, and CLI problems.
This page covers the most common issues you will run into when operating Hogsend, organized by symptom. Each section describes what you see, why it happens, and how to fix it.
Events not arriving
You are sending events from PostHog but nothing shows up in Hogsend.
Webhook URL is wrong
Symptom: PostHog's History tab shows delivery failures (4xx or 5xx errors).
Fix: Verify the webhook URL in PostHog > Data > Destinations. It must be:
https://your-hogsend-api.com/v1/webhooks/posthogCommon mistakes:
- Missing the
/v1/webhooks/posthogpath - Using
http://instead ofhttps:// - Using
localhost-- PostHog's servers cannot reach your local machine
Webhook secret mismatch
Symptom: PostHog's History tab shows 401 Unauthorized responses.
Fix: The x-posthog-webhook-secret header in your PostHog destination must exactly match the POSTHOG_WEBHOOK_SECRET environment variable on your Hogsend API service. Check both values:
# Check what Hogsend expects
# (look at the POSTHOG_WEBHOOK_SECRET env var in Railway or .env)
# Then compare with the header value in PostHog > Data > Destinations > your destination > HeadersIf you used hogsend init, the CLI set both values. If they got out of sync (e.g., you regenerated secrets), update both sides to match.
No event matchers configured
Symptom: PostHog shows thousands of deliveries but they are all $pageview, $autocapture, or other internal events. Your journey events are not being sent.
Fix: Add event matchers in the PostHog destination. Without matchers, PostHog sends every event. Add a matcher for each event your journeys care about (e.g., user_signed_up, trial_started). See PostHog Setup for the full walkthrough.
API is not reachable
Symptom: PostHog's History tab shows connection timeouts or DNS errors.
Fix:
- Check that the API is running:
curl https://your-hogsend-api.com/v1/health - If using Railway, check the service status in the Railway dashboard
- If you just deployed, wait for the health check to pass (~2 minutes)
- Check that your DNS (Cloudflare CNAME) points to the correct Railway domain
Events arrive but journeys don't trigger
Events are stored in Hogsend (visible via the admin API) but no journey instances are created.
Event name mismatch
Symptom: The event is stored but no journey picks it up.
Fix: The event name must exactly match the trigger.event in your journey definition. Event names are case-sensitive.
# Check what event name was stored
curl -H "Authorization: Bearer $ADMIN_API_KEY" \
"https://your-hogsend-api.com/v1/admin/events?limit=5"
# Check what event the journey expects
curl -H "Authorization: Bearer $ADMIN_API_KEY" \
"https://your-hogsend-api.com/v1/admin/journeys/your-journey-id"Common mismatches: user_signed_up vs user:signed_up, userSignedUp vs user_signed_up. PostHog sends the exact event name as captured in your app.
Journey is not enabled
Symptom: The event name matches but no enrollment happens.
Fix: Check two things:
- Runtime toggle -- the journey may have been disabled via the admin API:
curl -H "Authorization: Bearer $ADMIN_API_KEY" \
"https://your-hogsend-api.com/v1/admin/journeys/your-journey-id"If enabled: false, re-enable it:
curl -X PATCH "https://your-hogsend-api.com/v1/admin/journeys/your-journey-id" \
-H "Authorization: Bearer $ADMIN_API_KEY" \
-H "Content-Type: application/json" \
-d '{ "enabled": true }'- ENABLED_JOURNEYS env var -- the journey must be in the
ENABLED_JOURNEYSlist. If set to*, all journeys are enabled. Otherwise, it must be a comma-separated list that includes the journey ID.
Entry limit reached
Symptom: The user was enrolled before and the journey has entryLimit: "once".
Fix: Check the user's journey history:
curl -H "Authorization: Bearer $ADMIN_API_KEY" \
"https://your-hogsend-api.com/v1/admin/journeys/your-journey-id/states?userId=user_abc123"If there is an existing completed or active state and the journey has entryLimit: "once", the user cannot re-enter. To re-enroll, either cancel the existing instance or change the journey's entry limit.
Trigger conditions don't match
Symptom: The event arrives, the journey is enabled, but the trigger.where conditions filter it out.
Fix: Check the journey's trigger conditions and compare against the event properties:
# See the journey's trigger conditions
curl -H "Authorization: Bearer $ADMIN_API_KEY" \
"https://your-hogsend-api.com/v1/admin/journeys/your-journey-id"
# See the event properties
curl -H "Authorization: Bearer $ADMIN_API_KEY" \
"https://your-hogsend-api.com/v1/admin/events?userId=user_abc123&event=user_signed_up"If the journey requires plan == "pro" but the event has plan: "free", the condition fails silently.
User is unsubscribed or suppressed
Symptom: Everything matches but the entry guard rejects the user.
Fix: Check the user's subscription status:
curl -H "Authorization: Bearer $ADMIN_API_KEY" \
"https://your-hogsend-api.com/v1/admin/contacts/user_abc123/preferences"If unsubscribedAll: true or suppressed: true, the user will not be enrolled. See Email Operations for how to un-suppress a contact.
Emails not sending
Journeys are running but emails are not being delivered.
Invalid Resend API key
Symptom: Emails fail immediately with a Resend API error. Email status is failed.
Fix: Verify RESEND_API_KEY is set correctly and starts with re_. Check the Resend dashboard to confirm the key is active and has not been revoked.
Sending domain not verified
Symptom: Resend returns a domain verification error. Emails fail with status failed.
Fix: The domain in RESEND_FROM_EMAIL must be verified in your Resend account. Go to Resend > Domains and add your sending domain. Follow Resend's instructions to add the required DNS records (SPF, DKIM, DMARC).
If you are using the default [email protected], you need to verify hogsend.com in Resend, which is only possible if you control that domain.
Bounce suppression
Symptom: Emails are not sent to specific contacts. Other contacts receive emails normally.
Fix: The contact may be suppressed due to previous bounces. Check their preferences:
curl -H "Authorization: Bearer $ADMIN_API_KEY" \
"https://your-hogsend-api.com/v1/admin/contacts/user_abc123/preferences"If suppressed: true and bounceCount >= 3, the contact was auto-suppressed. See Email Operations for how to un-suppress them.
Resend webhooks not configured
Symptom: Emails show sent status but never progress to delivered, opened, or clicked.
Fix: This means Resend webhook events are not reaching Hogsend. Set up a webhook endpoint in Resend > Webhooks:
- URL:
https://your-hogsend-api.com/v1/webhooks/resend - Events:
email.delivered,email.opened,email.clicked,email.bounced,email.complained - Signing secret: Set this as
RESEND_WEBHOOK_SECRETin your Hogsend environment
Hatchet connection failures
The API or worker cannot connect to the Hatchet engine.
Invalid or missing token
Symptom: API logs show "failed to connect to Hatchet" or gRPC authentication errors. The worker fails to start.
Fix:
- Check that
HATCHET_CLIENT_TOKENis set in your environment - Verify the token is valid -- generate a new one from the Hatchet dashboard
- For local development, the Hatchet-Lite dashboard is at
localhost:8888(login:[email protected]/Admin123!!) - For Railway, open the Hatchet-Lite service URL and generate a token from the dashboard
Wrong gRPC endpoint
Symptom: Connection timeouts when the API or worker tries to reach Hatchet.
Fix: Check HATCHET_CLIENT_HOST_PORT:
- Local development:
localhost:7077 - Railway: Use the internal network address of the Hatchet-Lite service (not the public URL). Format:
hatchet-lite.railway.internal:7077
Also check HATCHET_CLIENT_TLS_STRATEGY:
- Local / Railway internal networking:
none - Public internet:
tls
Hatchet-Lite is not running
Symptom: Connection refused errors.
Fix:
- Local: Run
docker compose up -dand check that the Hatchet-Lite container is healthy:docker compose ps - Railway: Check the Hatchet-Lite service in the Railway dashboard. If it crashed, check its logs for database connection issues -- Hatchet-Lite needs its own Postgres instance
Database issues
Migration failures
Symptom: The API fails to deploy on Railway with a migration error in preDeployCommand.
Fix:
- Check the deploy logs in Railway for the specific migration error
- If a migration failed partway through, you may need to manually fix the database state
- Verify that
DATABASE_URLpoints to the correct Postgres instance - Check that the Postgres instance is running and accepting connections
# Test the connection locally
psql $DATABASE_URL -c "SELECT 1"Connection pool exhaustion
Symptom: Database connection errors under load. Queries timeout or return "too many connections".
Fix:
- Check the number of active connections:
SELECT count(*) FROM pg_stat_activity; - Railway's managed Postgres has connection limits based on your plan
- Consider using a connection pooler (e.g., PgBouncer) for high-throughput deployments
- Check for long-running transactions that hold connections open
Redis connection
Symptom: Worker logs show Redis connection errors. PostHog property caching is not working.
Fix:
- Verify
REDIS_URLis set and the Redis instance is running - Local: Check Docker:
docker compose ps-- Redis should be on port 6380 - Railway: Check the Redis service status and that it is linked to both API and worker services
- Redis is used for caching, not critical state. If Redis is down, the worker will fall back to fetching properties directly from PostHog (slower but functional)
Health check failing
Symptom: Railway shows the API service as unhealthy. The service keeps restarting.
Fix: Hit the health endpoint directly to see what is failing:
curl -v https://your-hogsend-api.com/v1/healthThe health check verifies database connectivity. Common causes of failure:
| Cause | Fix |
|---|---|
DATABASE_URL not set | Add the variable in Railway and link the Postgres instance |
| Postgres is still starting | Wait 1-2 minutes after initial deploy. The health check timeout is 120 seconds. |
| Migrations failed | Check deploy logs for migration errors |
| Port conflict | Ensure PORT is not hardcoded -- Railway sets it automatically |
CLI issues
Token invalid
Symptom: hogsend init or hogsend status returns an authentication error.
Fix:
- Railway token: Generate a new one at railway.com/account/tokens. Tokens can expire or be revoked.
- PostHog personal API key: Generate at PostHog > Settings > Personal API Keys. Must start with
phx_. Project API keys (starting withphc_) will not work for the CLI.
Project not found
Symptom: hogsend init cannot find your Railway project.
Fix:
- Make sure the Railway project exists and the template deploy completed successfully
- Check that your Railway token has access to the project (team tokens are scoped per team)
- If you have multiple Railway projects, the CLI will prompt you to select one
Services not discovered
Symptom: hogsend init finds the project but cannot find the API or worker services.
Fix: The CLI looks for services named hogsend-api and hogsend-worker. If you renamed them in Railway, the CLI will not find them automatically. Either rename them back or use the CLI's interactive selection to pick the correct services.
Getting more help
If you are stuck on an issue not covered here:
- Check the API logs in Railway (or your local terminal) -- most errors include enough context to diagnose the problem
- Check the Hatchet dashboard (
localhost:8888locally, or the Hatchet-Lite service URL on Railway) for workflow run details and failure reasons - Use the admin API to inspect events, journey states, and email sends -- see Monitoring for the full set of endpoints
- Open an issue on GitHub with the error message and relevant logs