Self-hosted US Congress monitoring platform with AI policy briefs, bill/member/topic follows, ntfy + RSS + email notifications, alignment scoring, collections, and draft-letter generator. Authored by: Jack Levy
3.8 KiB
Troubleshooting
Common issues encountered during development and deployment of PocketVeto.
502 Bad Gateway after rebuilding a container
Symptom
All API calls return 502. nginx error log shows:
connect() failed (111: Connection refused) while connecting to upstream,
upstream: "http://172.18.0.X:8000/api/..."
The IP in the error is the old IP of the container before the rebuild.
Root cause
When nginx uses upstream blocks, it resolves hostnames once at process startup and caches the result for the lifetime of the process. Rebuilding a container (e.g. docker compose build api && docker compose up -d api) assigns it a new Docker network IP. nginx still holds the old IP and all connections are refused.
Immediate fix
docker compose restart nginx
This forces nginx to re-resolve all upstream hostnames from Docker's internal DNS (127.0.0.11).
Permanent fix (already applied)
Replace upstream blocks with set $variable in proxy_pass. nginx only activates the resolver directive when a variable is used — making it re-resolve on each request cycle (every valid=N seconds).
resolver 127.0.0.11 valid=10s ipv6=off;
# BAD — resolves once at startup, caches forever
upstream api {
server api:8000;
}
location /api/ {
proxy_pass http://api;
}
# GOOD — re-resolves via resolver every 10 s
location /api/ {
set $api http://api:8000;
proxy_pass $api;
}
Wrong service name for docker compose exec
The API service is named api in docker-compose.yml, not backend.
# Wrong
docker compose exec backend alembic upgrade head
# Correct
docker compose exec api alembic upgrade head
Alembic migration not applied after rebuild
If a new migration file was added after the last image build, the API container won't have it baked in. The container runs alembic upgrade head at startup from the built image.
Fix: rebuild the API image so the new migration file is included, then restart:
docker compose build api && docker compose up -d api
Wrong postgres user
The database superuser is congress (set via POSTGRES_USER in .env / docker-compose.yml), not the default postgres.
# Wrong
docker compose exec postgres psql -U postgres pocketveto
# Correct
docker compose exec postgres psql -U congress pocketveto
Frontend changes not showing after editing source files
The frontend runs as a production Next.js build (NODE_ENV=production) — there is no hot reload. Code changes require a full image rebuild:
docker compose build frontend && docker compose up -d frontend
Static assets are cache-busted automatically by Next.js (content-hashed filenames), so a hard refresh in the browser is not required after the new container starts.
Celery tasks not reflecting code changes
Celery worker and beat processes also run from the built image. After changing any worker code:
docker compose build worker beat && docker compose up -d worker beat
Checking logs
# All services
docker compose logs -f
# Single service (last 50 lines)
docker compose logs --tail=50 api
docker compose logs --tail=50 nginx
docker compose logs --tail=50 worker
# Follow in real time
docker compose logs -f api worker
Inspecting the database
docker compose exec postgres psql -U congress pocketveto
Useful queries:
-- Recent notification events
SELECT event_type, bill_id, dispatched_at, created_at
FROM notification_events
ORDER BY created_at DESC
LIMIT 20;
-- Follow modes per user
SELECT u.email, f.follow_type, f.follow_value, f.follow_mode
FROM follows f
JOIN users u ON u.id = f.user_id
ORDER BY u.email, f.follow_type;
-- Users and their RSS tokens
SELECT id, email, rss_token IS NOT NULL AS has_rss_token FROM users;