Troubleshoot common issues

Fix common self-hosted Quackback problems: startup and migration errors, email provider conflicts, sign-in and OAuth callbacks, background jobs, IMAP, rate limits, and Docker issues.

JM
James Morton
Written By James MortonLast updated 1 day ago

Common problems with self-hosted Quackback deployments and how to fix them, from startup and database errors to email, sign-in, background jobs, and Docker issues.

Application won't start

Database connection failed

The application fails to start with connection errors.

1. Verify PostgreSQL is running

docker compose -f docker-compose.prod.yml ps
# or
systemctl status postgresql

2. Test the connection

psql "$DATABASE_URL" -c "SELECT 1"

3. Check the connection string format: postgresql://user:password@host:5432/database

4. For Docker networking: use the container or service name, not localhost, and make sure containers share a network.

Missing environment variable

The app checks its configuration at startup and exits with a message naming any missing or invalid variable.

  1. Check the required variables: DATABASE_URL, SECRET_KEY (32+ characters), and BASE_URL. REDIS_URL is not required (see A leftover REDIS_URL).
  2. Verify .env is loaded: docker compose -f docker-compose.prod.yml config shows the resolved values.
  3. Check for typos: variable names are case-sensitive, and there are no spaces around =.

More than one outbound email provider is configured

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

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 Configure email delivery.

Port already in use

# Find the process using port 3000
lsof -i :3000

Stop that process, or use a different port: set PORT (manual install) or APP_PORT (Docker Compose).

Database issues

Migration failed

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 (run 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. Make sure the 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.

Extension vector not found

Vector-related queries fail.

1. Install the extension:

CREATE EXTENSION IF NOT EXISTS vector;

2. If you run your own PostgreSQL container, use an image that ships pgvector, such as pgvector/pgvector:pg18.

Realtime updates don't arrive

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

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 Set up a reverse proxy.

Authentication problems

Users are signed out right after signing in

  1. Check BASE_URL: it must match the exact domain users visit, including the protocol (https://feedback.example.com).
  2. Check cookies: cookies require HTTPS in production.
  3. Clear browser data: delete cookies for the domain, or try a private window.

Sign-in codes not received

  1. Check the logs. If no email provider is configured, sign-in codes are printed to the server log.
  2. Verify the email configuration: one of SMTP (EMAIL_SMTP_HOST, EMAIL_SMTP_PORT, EMAIL_SMTP_USER, EMAIL_SMTP_PASS), Amazon SES (EMAIL_SES_ACCESS_KEY_ID, EMAIL_SES_SECRET_ACCESS_KEY, EMAIL_SES_REGION), or Resend (EMAIL_RESEND_API_KEY), plus EMAIL_FROM.
  3. Check the spam folder.
  4. Test delivery with your provider's test tools, for example swaks --to [email protected] --server smtp.example.com.

OAuth redirect errors

"Redirect URI mismatch" or similar errors from a sign-in provider.

1. Verify the callback URL registered with the provider:

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

Replace github with the provider (google, discord, and so on). 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: the URI must match exactly.

3. Verify the client ID and secret: copy them again from the provider dashboard and check for whitespace.

Background processing issues

Background jobs are not processing

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

1. Check QUACKBACK_ROLE on every replica. web replicas serve HTTP and enqueue jobs but never run 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. On a web replica, checks.workers reports expected: false and the check passes.

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

IMAP inbound email is not creating conversations

1. Verify all four required variables are set: EMAIL_INBOUND_PROVIDER=imap, IMAP_HOST, IMAP_USER, and IMAP_PASSWORD. The poller stays off if any one is missing. See Receive email over IMAP.

2. Confirm a worker is running: the poller runs only where QUACKBACK_ROLE is worker or all.

3. Check IMAP_MAILBOX and IMAP_TLS: IMAP_MAILBOX defaults to INBOX. 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 email channel is enabled in Admin > Settings > Channels.

Everyone shares one rate limit

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

The app sits behind a proxy with TRUSTED_PROXY_HOPS=0. Set it to the number of proxies in front of the app, or set TRUSTED_CLIENT_IP_HEADER to a client-IP header your proxy sets. See Set up a reverse proxy.

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.

Performance issues

Slow page loads

1. Check database performance (requires the pg_stat_statements extension):

SELECT query, calls, mean_exec_time
FROM pg_stat_statements
ORDER BY mean_exec_time DESC
LIMIT 10;

2. Increase resources: more RAM for PostgreSQL, more CPU for the application.

High memory usage

1. Monitor over time: docker stats

2. Tune PostgreSQL:

shared_buffers = 256MB  # about 25% of RAM
work_mem = 16MB

3. Set up health checks and auto-restart.

Integration issues

Slack notifications not sending

  1. Check the integration status in Admin > Settings > Integrations > Slack and look for error messages.
  2. Verify channel access: the app must be invited to private channels, and the channel may have been deleted.
  3. Check event mappings: make sure events are configured and the right channel is selected.
  4. Reconnect: click Reconnect and authorize again in Slack.

Webhook deliveries failing

1. Check that the endpoint is reachable:

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

2. Verify HTTPS: webhooks require HTTPS endpoints with a valid certificate.

3. Check response codes: the endpoint must return 2xx. 4xx errors are not retried (except 429).

Docker issues

App isn't reachable, or there's no app container

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

Use the production Compose file. A bare docker compose up -d uses the repository'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

The container exits immediately with ERR_INVALID_URL, often on DATABASE_URL.

Remove quotes from your .env. Docker's --env-file and Compose's env_file don't strip quotes or inline # comments, so DATABASE_URL="postgresql://..." is passed with the quotes attached. Use plain KEY=value.

Container keeps restarting

# Check logs
docker compose -f docker-compose.prod.yml logs app --tail 100

# Check health
docker compose -f docker-compose.prod.yml ps

# Verify the environment
docker compose -f docker-compose.prod.yml config

Database volume issues

Data doesn't persist, or you see permission errors.

1. Check the volume mount:

volumes:
  - postgres_data:/var/lib/postgresql

2. Fix permissions: sudo chown -R 999:999 /path/to/volume

Out of disk space

# Check disk usage
df -h
docker system df

# Clean up unused Docker data
docker system prune -a

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

Getting help

Before asking for help, gather:

  1. The exact error messages
  2. Logs: docker compose -f docker-compose.prod.yml logs app --tail 200 > app-logs.txt
  3. Your environment, with secrets removed
  4. Steps to reproduce

Then open an issue on GitHub Issues or ask in GitHub Discussions. Include:

  • Environment: Quackback version, deployment method (Docker or Bun), PostgreSQL version, OS
  • Problem: what's wrong
  • Steps to reproduce
  • Expected behaviour and actual behaviour
  • Logs: the relevant log output, pasted in a code block

Was this helpful?

Your feedback shapes what we write next.