Kurir / Troubleshooting

Troubleshooting

IMAP connection failures

Wrong host or port

Make sure you are using the correct IMAP host for your provider:

ProviderIMAP HostPort
Gmailimap.gmail.com993
Outlookoutlook.office365.com993
iCloudimap.mail.me.com993
Yahooimap.mail.yahoo.com993

All connections use TLS on port 993 by default.

App password required

Most email providers require an app-specific password rather than your regular account password when two-factor authentication (2FA) is enabled:

Two-factor authentication (2FA)

If your provider has 2FA enabled and you are not using OAuth, you must use an app password. Regular passwords will be rejected with an authentication error.

Sync stuck / “Sync already in progress”

If the sync process crashes or is interrupted, the isSyncing lock can remain set in the database, blocking future syncs. The lock auto-clears after 5 minutes. If you need to clear it immediately:

# Docker Compose (production)
docker compose -f docker-compose.production.yml exec postgres \
  psql -U kurir -c 'UPDATE "SyncState" SET "isSyncing" = false;'

# One-command installer
cd /opt/kurir && docker compose exec postgres \
  psql -U kurir -c 'UPDATE "SyncState" SET "isSyncing" = false;'

Then trigger a fresh sync:

docker compose exec app pnpm sync-user --all

Firewall and port issues

Kurir requires ports 80 and 443 to be open for Caddy to serve HTTPS traffic and obtain Let’s Encrypt certificates.

Check if the ports are available:

ss -tlnp | grep -E ':(80|443)\s'

If another service is using these ports (e.g. Apache, Nginx), either stop it or configure it as a reverse proxy to Kurir.

For cloud providers, also check your security group / firewall rules to ensure inbound traffic on 80 and 443 is allowed.

DNS and domain configuration

Caddy needs a valid domain name pointed at your server to provision Let’s Encrypt certificates.

  1. Create an A record pointing your domain (e.g. mail.example.com) to your server’s public IP.
  2. Wait for DNS propagation (usually a few minutes, up to 48 hours).
  3. Verify with: dig +short mail.example.com

If Caddy fails to obtain a certificate, check its logs:

docker compose logs proxy

Common issues:

OAuth token refresh issues

OAuth tokens expire and are refreshed automatically. If token refresh stops working:

To re-authenticate, the user can disconnect and reconnect their email account from the Settings page.

Docker container won’t start

Check container logs

# All services
docker compose logs

# App only
docker compose logs app

# Last 50 lines
docker compose logs app --tail 50

Common startup errors

“NEXTAUTH_SECRET is not set” — Your .env file is missing required variables. See Configuration.

“Connection refused” to PostgreSQL — The database container may not be ready yet. The app container has a health check dependency on PostgreSQL, but if you see this in logs, wait a moment and check again.

Out of memory — The default Docker Compose setup limits the app to 1024 MB. If your server has limited RAM, check docker stats and consider reducing the NODE_OPTIONS --max-old-space-size value.

Container keeps restarting

Check the exit code:

docker compose ps

An exit code of 137 usually means the container was killed due to memory limits (OOMKilled).

Database connection errors

“Connection refused” — Verify PostgreSQL is running:

docker compose ps postgres

“Authentication failed” — The POSTGRES_PASSWORD in your .env must match what PostgreSQL was initialized with. If you change the password after first run, you need to either reset the database volume or update the password inside PostgreSQL directly.

“Too many connections” — The default connection limit is 10 (set in DATABASE_URL). If you see this error, restart the app container to release stale connections:

docker compose restart app

Search not working

Kurir uses PostgreSQL full-text search with a search_vector column and GIN index. If search returns no results after a restore or fresh install, the search vector migration may not have been applied:

docker compose -f docker-compose.production.yml exec -T postgres \
  psql -U kurir < prisma/migrations/search_vector.sql

Getting more help

If your issue is not covered here:

  1. Check the GitHub Issues for known problems and solutions.
  2. Open a new issue with your Docker logs and environment details (redact secrets).