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.

It must match the API's PORT (4000). The default and apps/esu/.env.example now use http://localhost:4000/api/v1, but a .env copied before that change still says 3000 — set API_BASE_URL=http://localhost:4000/api/v1. The symptom in the app is DMs that only update on refresh.

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) 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