Troubleshooting¶
Diagnosing a problem¶
Start by identifying which layer the error comes from:
| Where to look | What it covers |
|---|---|
| Browser console (F12 → Console) | Frontend JavaScript errors |
| Browser network tab (F12 → Network) | API call failures, CORS errors, HTTP status codes |
Terminal running npm run dev |
Backend errors, stack traces |
docker compose logs -f keycloak |
Keycloak startup, authentication errors |
docker compose logs -f postgres |
Database connection errors |
Authentication errors¶
JWT audience invalid¶
The access token is missing the aud claim. Add the Audience mapper in Keycloak Admin:
- Open Keycloak Admin:
http://localhost:8080 - Select realm ronl
- Navigate to Clients → ronl-business-api → Client scopes → ronl-business-api-dedicated
- Click Add mapper → By configuration → Audience
- Set:
- Name:
audience - Included Client Audience:
ronl-business-api - Add to access token: ON
- Save, then log out and log back in
Verify by decoding your token at jwt.io and checking for "aud": "ronl-business-api".
Roles not appearing in JWT¶
All users show as citizen even though a test user is configured as caseworker.
The realm_roles protocol mapper is missing. Add it in Keycloak Admin:
- Clients → ronl-business-api → Client scopes → ronl-business-api-dedicated → Mappers
- If
realm_rolesis missing, click Add mapper → By configuration → User Realm Role - Set:
- Name:
realm_roles - Multivalued: ON
- Token Claim Name:
realm_access.roles - Add to access token: ON
- Save, then log out and log back in
Login redirects to blank page¶
Cause: Invalid redirect URIs in the Keycloak client.
- Clients → ronl-business-api → Settings
- Set Valid Redirect URIs to
* - Set Valid Post Logout Redirect URIs to
* - Set Web Origins to
+ - Save
Token expired¶
This is expected — access tokens have a 15-minute lifetime. Log out and log back in. Token refresh is a planned production feature.
CORS errors¶
CORS policy blocking Keycloak¶
Access to XMLHttpRequest at 'http://localhost:8080/realms/ronl/...'
from origin 'http://localhost:5173' has been blocked by CORS policy
- Clients → ronl-business-api → Settings
- Set Web Origins to
+(inherits all valid redirect URIs) - Save
If the error persists, verify CORS_ORIGIN in packages/backend/.env matches http://localhost:5173 exactly (no trailing slash).
Backend API errors¶
Health check returns unhealthy dependencies¶
Expected:
{
"status": "healthy",
"services": {
"keycloak": { "status": "up" },
"operaton": { "status": "up" }
}
}
If keycloak is "down": check Docker — docker compose ps — and that Keycloak is listening on port 8080.
If operaton is "down": check that https://operaton.open-regels.nl is reachable from your network.
Port already in use¶
Find and stop whatever is occupying the port:
# Linux/Mac
lsof -i :3002
kill -9 <PID>
# Windows
netstat -ano | findstr :3002
taskkill /PID <PID> /F
Alternatively, change the port in packages/backend/.env:
And update VITE_API_URL in packages/frontend/.env to match.
API returns 500 Internal Server Error¶
Check the backend terminal for a stack trace. Common causes:
- Operaton unreachable (
OPERATON_BASE_URLwrong or service down) - Invalid request body (missing required fields)
- Missing environment variable (check
packages/backend/.envis populated)
Zorgtoeslag calculation fails¶
- Open browser DevTools → Network tab
- Find the request to
/v1/decision/berekenrechtenhoogtezorg/evaluate - Check the response status — should be
200 - Common causes:
audclaim missing from token → see JWT audience fix above- Operaton service unreachable
- Invalid input variable types
Test user issues¶
Can't log in with test users¶
Verify the users exist in Keycloak:
- Open Keycloak Admin → Users
- Search for
test-citizen-utrecht - Should find 8 users total (citizen + caseworker × 4 municipalities)
If the users are missing, the realm import did not run. Reimport:
docker compose down
docker volume rm ronl-business-api_keycloak-data
docker compose up -d
# Wait 60 seconds for Keycloak to start and import the realm
npm run dev
Browser issues¶
Changes not visible after saving¶
Vite HMR should update automatically. If it doesn't:
If that fails: F12 → Application → Clear storage → Clear site data → reload.
Regular Chrome not working, Incognito works¶
Cause: Browser cache holding stale CORS errors.
- Close all Chrome windows completely
- Reopen Chrome
- Try again
If still broken, use Incognito for the remainder of the session. This is a browser cache issue, not a code issue.
Windows-specific issues¶
Line ending warnings¶
Emergency reset¶
When everything is broken and you want a clean slate:
# 1. Stop dev servers
Ctrl+C
# 2. Wipe Docker (containers + volumes = all Keycloak data)
docker compose down -v
docker system prune -f
# 3. Wipe Node modules
rm -rf node_modules
rm -rf packages/*/node_modules
# 4. Fresh install and start
npm install
npm run build --workspace=@ronl/shared
npm run docker:up
# Wait 60 seconds
npm run dev
Diagnostic commands¶
# Check tool versions
node --version
npm --version
docker --version
# Check running containers
docker compose ps
docker compose logs keycloak --tail=50
# Check ports in use (Linux/Mac)
sudo lsof -i :5173 # frontend
sudo lsof -i :3002 # backend
sudo lsof -i :8080 # keycloak
# Check ports in use (Windows)
netstat -ano | findstr :5173
netstat -ano | findstr :3002
netstat -ano | findstr :8080
# API health with formatted output
curl http://localhost:3002/v1/health | jq
# Keycloak health
curl http://localhost:8080/health/ready