Skip to content

Troubleshooting

Read the judge's log first: docker logs --tail 100 moj-judge answers most of these.

Judging

SymptomCauseFix
Not on /status/MOJ_URL points at the web app or the client APIcurl -i "$MOJ_URL/health". JSON is the right host; HTML is the web app.
Rejected at the handshakeJUDGE_NAME is not a judge in the consoleThere is no automatic registration.
Rejected with a 403The key does not matchCompare printf %s "$JUDGE_KEY" | sha256sum with the stored hash, or issue a new key.
Flapping online and offlineTwo containers share one nameGive the second its own record.
Refused entirelyBlocked or disabled in the consoleBoth are switches on its row.
Every claim times out in developmentA host firewall filters the Docker bridgeUse the judge profile, which is on host networking.
TLS fails on the judge boxClock skewtimedatectl
Queued, nothing claims itNo judge is online/status/
QueuedNo online judge has that problem or languageThe judge's row lists both. Fix the data, then docker restart moj-judge.
QueuedPinned to an offline judgeIt waits for that judge.
Queued while another tier is idleOnly the lowest online tier claimsDisable the hung judge.
A rejudge crawlsRejudge priorities are skipped while the tier is busyIt speeds up when things go quiet. Watch /admin/jobs/.
Stuck in ProcessingA judge claimed it and diedRequeued after 60 s without a heartbeat or 15 min without progress; a second failure is an internal error.

Sign-in and deployment

SymptomCauseFix
Every page behaves as though signed out, slowlyThe backend cannot fetch the keys at AUTH_JWKS_URLnpx convex env get AUTH_JWKS_URL. In production it must reach https://<domain>/api/auth/jwks.
The same, in developmentA host firewall filters the Docker bridgenpm run setup inlines the key set as a data: URI and leaves AUTH_URL unset. Rotating the signing keys then needs another npm run setup.
npx convex deploy cannot authenticateA missing or unquoted variableBoth CONVEX_SELF_HOSTED_URL and CONVEX_SELF_HOSTED_ADMIN_KEY are needed, and the key contains a |. Generate another with exec convex-backend ./generate_admin_key.sh; old keys stay valid.
No CONVEX_DEPLOYMENT set.env.local is missing or names a dead deploymentnpm run setup
Hex-decoded key was 31 bytes, not 32INSTANCE_SECRET is not 64 hex charactersopenssl rand -hex 32
Stored data is suddenly unreadableINSTANCE_SECRET changedPut the old value back, or restore from an export.
The backend connects to a database and exitsThe database does not existinfra/scripts/postgres-init/01-databases.sh only runs on a fresh volume.
Missing table errorsThe migrations have not runnpm run db:migrate -w apps/web
Port 5433 is in useSomething else holds the published portss -ltnp | grep 5433
Read-only with errors in the logFull diskdf -h, always first.
A fallback fontThe fonts were not copied into the imageexec web ls public/fonts
PDF statements failThe rendering binary is missingexec web typst --version, or set TYPST_BIN. The error is on /admin/jobs/.
Maths appears as plain text with bracesThe maths stylesheet did not loadThe CSS is missing, not the maths.
The theme does not stickSigned out, it is per-browserSigned in it follows the account; the default is on /admin/config/branding/.
bash
# Create a missing database and migrate
docker compose -f infra/compose.prod.yml --project-directory . exec postgres \
  psql -U moj -c 'CREATE DATABASE moj_auth OWNER moj'
npm run db:migrate -w apps/web

Resetting a development stack

bash
# everything, including both databases
docker compose -f infra/compose.dev.yml --project-directory . down -v
rm -f .env.local apps/web/.env.local
npm run setup

# keep the data: re-push the functions, re-seed, or re-seed over existing rows
npx convex dev --once
npx convex run seed:run '{}'
npx convex run seed:run '{"force": true}'

Everything is slow

Check /status/ for judge load, /admin/jobs/ for a running batch rejudge, docker stats for a container out of memory, df -h for disk, and the dashboard's logs for functions that are erroring.

Released under the AGPL-3.0-only licence.