Skip to content

Troubleshooting

Local development problems, roughly in the order new developers hit them. For production incidents see Runbooks.

Install and build

pnpm install produces lockfile changes I did not make

You are on the wrong pnpm version. The repo pins pnpm@9.0.0:

bash
corepack enable
corepack prepare pnpm@9.0.0 --activate
pnpm --version   # must print 9.0.0
git checkout pnpm-lock.yaml
pnpm install

Cannot find module '@playpals/db'

The shared packages have not been built. Services import from dist/, not source:

bash
pnpm build

If it persists, the Prisma client is missing:

bash
cd packages/database && pnpm db:generate && pnpm build

TypeScript cannot find Prisma model types

packages/database/generated/ is git-ignored and produced by prisma generate. A fresh clone has no types until you generate them. Same fix as above.

Nuclear option

bash
rm -rf node_modules apps/*/node_modules packages/*/node_modules
rm -rf .turbo apps/*/.turbo packages/*/.turbo
pnpm install
cd packages/database && pnpm db:generate && cd ../..
pnpm build

Database

Can't reach database server at localhost:5432

bash
docker compose ps                    # is playpals-db running?
docker compose up -d db
docker compose logs db --tail 50

Postgres takes a few seconds to initialise on first start. If something else on your machine already owns 5432 (a Homebrew Postgres, for instance), either stop it or remap the port in docker-compose.yaml.

Migration fails with a checksum or drift error

Someone edited an already-applied migration, or your local database is out of sync. Locally the fix is to reset:

bash
docker compose down -v
docker compose up -d db redis
cd packages/database && pnpm db:migrate && pnpm db:seed

docker compose down -v deletes the volume and therefore all local data. Never run the equivalent against a shared environment.

The schema in my database does not match schema.prisma

bash
cd packages/database && pnpm exec prisma migrate status

Redis and background jobs

NOAUTH Authentication required

The local Redis runs with --requirepass playpalz. Your connection string must carry the password:

bash
REDIS_URL="redis://:playpalz@localhost:6379"

This is the single most common local misconfiguration. Its symptom is not an obvious error in the UI — media uploads succeed but never produce thumbnails, and realtime events silently do not arrive.

Uploaded images never get thumbnails

The pipeline is: API writes the original to object storage → API enqueues a job → ogun processes it. Check each link:

bash
# 1. Is the worker running?
pnpm --filter @playpals/ogun dev

# 2. Are jobs reaching the queue?
docker exec -it playpals-redis redis-cli -a playpalz KEYS 'bull:media-processing:*'

# 3. Are they failing?
docker exec -it playpals-redis redis-cli -a playpalz LRANGE 'bull:media-processing:failed' 0 -1

ogun needs valid SPACES_* credentials to read the original and write variants. Without them it will pick up jobs and fail every one. See Media Pipeline.

Video posts stay in processing forever

Video goes to Mux, and the media record is only completed when Mux calls the webhook at POST /api/v1/webhooks/mux. Locally that callback cannot reach your laptop unless you tunnel it:

bash
ngrok http 4000
# then point the Mux webhook at https://<id>.ngrok.io/api/v1/webhooks/mux

Realtime

The socket connects and immediately disconnects

esu verifies the JWT the API issued, so both services must share the same JWT_SECRET. Compare apps/api/.env and apps/esu/.env. A mismatch presents as an instant disconnect with an auth error in the esu log.

Joining a DM or room is rejected with AUTHZ_DENIED

esu does not query the database for authorization. It calls back into the API (GET /api/v1/dm/:conversationId/authz and /room/:roomId/authz) using API_BASE_URL. If that points at the wrong port, every join is denied.

The default in apps/esu/.env.example is http://localhost:3000/api/v1, but the API's own .env.example sets PORT=4000. Set API_BASE_URL=http://localhost:4000/api/v1 to match.

Messages send but nobody receives them

The API fans out realtime events by calling esu's interservice admin endpoint. Check that the API's REALTIME_SERVICE_URL (http://localhost:4010/admin) and REALTIME_ADMIN_TOKEN match what esu expects in its own REALTIME_ADMIN_TOKEN.

Mobile

[Config] Missing env var: EXPO_PUBLIC_API_URL

Create apps/mobile/.env with EXPO_PUBLIC_API_URL and EXPO_PUBLIC_REALTIME_URL. See Local Setup.

Every API call 404s

EXPO_PUBLIC_API_URL must include the /api/v1 suffix — it is used verbatim as the axios baseURL.

The app cannot reach the API from a physical device

localhost on a phone means the phone. Use your machine's LAN IP and allow inbound connections on ports 4000 and 4010.

Metro serves stale code, or a module suddenly cannot be resolved

bash
pnpm --filter @playpals/mobile start -- --clear

If that does not fix it, remove apps/mobile/.expo and restart.

The app crashes on launch after I installed a dependency

Native modules and config plugins are compiled into the development build. Installing them does not change the binary already on your simulator. Produce a new development build — see Builds & Releases.

Expo Go will not open the app

It cannot. The app depends on native modules (LiveKit / WebRTC, notifications, Bugsnag) that Expo Go does not include. Use the development client.

Ports already in use

PortService
3000web (Next.js)
4000api
4005anansi
4010esu
5173docs
5432Postgres
6379Redis
7880–7882LiveKit
bash
lsof -i :4000
kill -9 <pid>

Still stuck

  1. Read the service's .env.example — the answer is usually a missing variable.
  2. Check the service's config module (src/configs/index.ts) to see what it actually reads and what it silently defaults to.
  3. Turn up logging: backend services use pino, and esu logs every inbound and outbound socket event when SOCKET_EVENT_LOGGING=true.

Internal documentation — PlayPalz platform