Skip to content

Troubleshooting

Common issues and solutions for self-hosted Quackback deployments.

Application Won't Start

"Database connection failed"

Symptoms: Application fails to start with connection errors.

Solutions:

  1. Verify PostgreSQL is running

    docker compose ps
    # or
    systemctl status postgresql
  2. Test connection

    psql "$DATABASE_URL" -c "SELECT 1"
  3. Check connection string format

    postgresql://user:password@host:5432/database
    
  4. For Docker networking

    • Use container name, not localhost
    • Ensure containers are on same network

"Missing environment variable"

Symptoms: Startup error about missing configuration.

Solutions:

  1. Check required variables

    # Must be set:
    DATABASE_URL
    SECRET_KEY   # 32+ characters
    BASE_URL
  2. Verify .env is loaded

    docker compose config  # Shows resolved values
  3. Check for typos

    • Variable names are case-sensitive
    • No spaces around =

"Port already in use"

Symptoms: Bind error on startup.

Solutions:

# Find process using port 3000
lsof -i :3000
 
# Kill it
kill -9 <PID>
 
# Or use different port
PORT=8080 bun run start

Database Issues

"Migration failed"

Symptoms: Database migrations don't complete.

Solutions:

  1. Read the startup log. Before it changes anything, the migrator checks the database and lists every problem it finds with the fix, for example:

    • PostgreSQL older than 14
    • pgvector missing or older than 0.5.0 (ALTER EXTENSION vector UPDATE; as a superuser)
    • pg_trgm not available (install the PostgreSQL contrib package)
    • the database user lacks the TEMPORARY privilege (GRANT TEMPORARY ON DATABASE quackback TO your_user;)

    If a migration itself fails, the log names it. All migrations in a run share one transaction, so a failure rolls the whole run back and the next start retries from the same point.

  2. Ensure database user has permissions

    GRANT ALL PRIVILEGES ON DATABASE quackback TO your_user;
    GRANT ALL PRIVILEGES ON SCHEMA public TO your_user;
  3. Don't interrupt a long first start. After a large upgrade, the first start can take several minutes. Stopping the container rolls the run back and the next start begins again.

  4. Reset and retry (development only)

    bun run db:reset
    bun run db:migrate

Only use db:reset in development environments. This will delete all data.

"Extension pgvector not found"

Symptoms: Vector-related queries fail.

Solutions:

  1. Install extension

    CREATE EXTENSION IF NOT EXISTS vector;
  2. Use pgvector image for Docker

    services:
      postgres:
        image: pgvector/pgvector:pg18

Realtime updates don't arrive

Symptoms: New messages, presence, or inbox updates only show after a page refresh.

Solution: Realtime uses PostgreSQL LISTEN/NOTIFY, which a transaction-mode pooler drops. Point DATABASE_URL at the database directly or at a session-mode pooler. If a reverse proxy buffers streaming responses, see Live chat updates arrive late.

Authentication Problems

"Invalid session" after login

Symptoms: Users get logged out immediately or can't stay logged in.

Solutions:

  1. Check BASE_URL

    • Must match exact domain users access
    • Include protocol: https://feedback.example.com
  2. Check cookies

    • Cookies require HTTPS in production
    • Verify domain settings
  3. Clear browser data

    • Delete cookies for the domain
    • Try incognito mode

OTP codes not received

Symptoms: Users don't receive magic link emails.

Solutions:

  1. Check the logs
    • OTP codes print to the server log if no email provider is configured

In development mode without email configuration, OTP codes are printed to the server console for easy testing.

  1. Verify email configuration

    # SMTP
    EMAIL_SMTP_HOST
    EMAIL_SMTP_PORT
    EMAIL_SMTP_USER
    EMAIL_SMTP_PASS
    # or SES: EMAIL_SES_ACCESS_KEY_ID, EMAIL_SES_SECRET_ACCESS_KEY, EMAIL_SES_REGION
    # or Resend: EMAIL_RESEND_API_KEY
    EMAIL_FROM
  2. Check spam folder

  3. Test email delivery

    # Many SMTP providers have test tools
    swaks --to test@example.com --server smtp.example.com

"More than one outbound email provider is configured"

Symptoms: The app exits at startup and the log lists two or more email providers with their variables.

Solution: Configure exactly one of SMTP, Amazon SES, or Resend, and remove the others' variables. If you keep a Resend key only to receive inbound mail through Resend while SMTP or SES sends, set EMAIL_INBOUND_PROVIDER=resend. See Email.

OAuth redirect errors

Symptoms: "Redirect URI mismatch" or similar OAuth errors.

Solutions:

  1. Verify callback URL

    https://your-domain.com/api/auth/callback/github
    

    Custom OIDC providers added before 0.14 may still use /api/auth/oauth2/callback/<id>. Register whichever URI the provider's Edit view in Quackback shows.

  2. Check for trailing slashes

    • Must match exactly in provider settings
  3. Verify client ID/secret

    • Re-copy from provider dashboard
    • Check for whitespace

Performance Issues

Slow page loads

Symptoms: Pages take several seconds to load.

Solutions:

  1. Check database performance

    -- Find slow queries
    SELECT query, calls, mean_time
    FROM pg_stat_statements
    ORDER BY mean_time DESC
    LIMIT 10;
  2. Add database indexes

    • Check for missing indexes on filtered columns
  3. Increase resources

    • More RAM for PostgreSQL
    • More CPU for application

High memory usage

Symptoms: Application or database using excessive memory.

Solutions:

  1. Check for memory leaks

    # Monitor over time
    docker stats
  2. Tune PostgreSQL

    shared_buffers = 256MB  # ~25% of RAM
    work_mem = 16MB
  3. Restart periodically

    • Set up health checks and auto-restart

Background Processing Issues

Background jobs are not processing

Symptoms: Webhooks, notifications, workflows, AI jobs, or scheduled analytics refreshes never fire, even though the app is up and requests succeed.

Solutions:

  1. Check QUACKBACK_ROLE on every replica

    • web-role replicas serve HTTP and enqueue jobs but never consume them
    • At least one replica needs QUACKBACK_ROLE=worker or the default all
    docker compose -f docker-compose.prod.yml exec app env | grep QUACKBACK_ROLE
  2. Check the readiness probe's worker status

    curl http://localhost:3000/api/health/ready

    Look at checks.workers in the response. expected: true with running: false means the job worker didn't start; check the app logs for the error.

  3. See Scale with multiple replicas for how web and worker roles split.

On a web-role replica, checks.workers reports expected: false and the check passes. Workers run on worker and all replicas only.

IMAP inbound email is not creating conversations

Symptoms: Emails sent to your support mailbox never appear as conversations.

Solutions:

  1. Verify all four required variables are set

    EMAIL_INBOUND_PROVIDER=imap
    IMAP_HOST
    IMAP_USER
    IMAP_PASSWORD

    The poller silently stays off if any one is missing. See Receive email over IMAP.

  2. Confirm a worker replica is running

    • The IMAP poller only runs where QUACKBACK_ROLE is worker or all, same as any other background job
  3. Check IMAP_MAILBOX and IMAP_TLS

    • IMAP_MAILBOX defaults to INBOX; point it at the mailbox you're actually receiving mail in
    • IMAP_TLS defaults to true (port 993); set it to false only for a plaintext connection on port 143
  4. Check the logs for connection errors

    docker compose -f docker-compose.prod.yml logs app --tail 100 | grep imap
  5. Confirm the conversations channel is enabled in Admin > Settings > Channels

Everyone shares one rate limit

Symptoms: Visitors get rate-limited at the same moment, and the log warns about proxy headers.

Solution: The app sits behind a proxy with TRUSTED_PROXY_HOPS=0. Set it to the number of proxies in front of the app. See Set the trusted proxy hops.

A leftover REDIS_URL

Quackback no longer uses Redis or Dragonfly. A REDIS_URL from an older install is ignored and safe to delete, along with the Redis or Dragonfly service.

Integration Issues

Slack notifications not sending

Symptoms: Connected but no messages appear.

Solutions:

  1. Check integration status

    • Admin → Settings → Integrations → Slack
    • Look for error messages
  2. Verify channel access

    • App must be invited to private channels
    • Channel may have been deleted
  3. Check event mappings

    • Ensure events are configured
    • Verify correct channel selected
  4. Reconnect integration

    • Click "Reconnect"
    • Re-authorize in Slack

Webhook deliveries failing

Symptoms: Webhooks show failed status.

Solutions:

  1. Check endpoint availability

    curl -X POST https://your-endpoint.com/webhook \
      -H "Content-Type: application/json" \
      -d '{"test": true}'
  2. Verify HTTPS

    • Webhooks require HTTPS endpoints
    • Check certificate validity
  3. Check response codes

    • Endpoint must return 2xx
    • 4xx errors don't retry (except 429)

Docker Issues

App isn't reachable / no app container

Symptoms: docker compose up -d starts the datastores but Quackback itself never runs.

Solution: Use the production compose file. A bare docker compose up -d uses the repo's root docker-compose.yml, which is development infrastructure only (PostgreSQL, object storage, and a mail catcher, with no app service). Self-host with:

cp .env.prod.example .env   # fill in your values
docker compose -f docker-compose.prod.yml up -d
docker compose -f docker-compose.prod.yml logs app

ERR_INVALID_URL at startup (with --env-file)

Symptoms: The container exits immediately with ERR_INVALID_URL, often on DATABASE_URL.

Solution: Remove quotes from your .env. Docker's --env-file does not strip quotes or inline # comments. It reads everything after = literally, so DATABASE_URL="postgresql://..." is passed with the quotes attached. Use plain KEY=value.

Container keeps restarting

Symptoms: Container in restart loop.

Solutions:

  1. Check logs

    docker compose logs app --tail 100
  2. Check health

    docker compose ps
  3. Verify environment

    docker compose config

Database volume issues

Symptoms: Data not persisting or permission errors.

Solutions:

  1. Check volume mount

    volumes:
      - postgres_data:/var/lib/postgresql
  2. Fix permissions

    sudo chown -R 999:999 /path/to/volume

Out of disk space

Symptoms: Write errors, container failures.

Solutions:

  1. Clean up Docker

    docker system prune -a
  2. Check disk usage

    df -h
    docker system df

docker system prune -a removes all unused images, containers, and networks. Use with caution in production.

Getting Help

Collect Diagnostic Info

Before asking for help, gather:

  1. Error messages (exact text)
  2. Logs
    docker compose logs app --tail 200 > app-logs.txt
  3. Environment (redact secrets)
  4. Steps to reproduce

Support Channels

Issue Template

Use this template when reporting issues to help maintainers understand and resolve your problem faster.

**Environment**
- Quackback version:
- Deployment method: Docker / Bun
- PostgreSQL version:
- OS:
 
**Problem**
[Describe the issue]
 
**Steps to Reproduce**
1.
2.
3.
 
**Expected Behavior**
[What should happen]
 
**Actual Behavior**
[What actually happens]
 
**Logs**

[Relevant log output]

Next Steps