Troubleshooting
Common issues and solutions for RiDDiX - Matrix Synapse Panel.
Installation & Startup
Database connection refused
Error: Connection refused or ECONNREFUSED on startup.
Causes:
- PostgreSQL is not running
DATABASE_URLis incorrect- Database container hasn't finished starting
Solutions:
- Check PostgreSQL is running:
docker compose ps db - Verify
DATABASE_URLmatches your database credentials - The app waits for the database health check — check
docker compose logs db
Prisma migration failed
Error: prisma migrate deploy fails during startup.
Causes:
- Database schema conflicts from manual changes
- Missing migration files
Solutions:
- Check migration logs:
docker compose logs app - If starting fresh: remove the database volume and restart
docker compose down -v
docker compose up -d
SESSION_SECRET too short
Error: Application fails to encrypt data or sessions.
Solution: Generate a proper 64-character hex string:
openssl rand -hex 32
Synapse Connectivity
Diagnostics show "Synapse not reachable"
Causes:
- Incorrect Internal URL
- Synapse is not running
- Network isolation (different Docker networks)
Solutions:
- Verify the Internal URL is reachable from the portal container:
docker compose exec app wget -qO- http://synapse:8008/_matrix/client/versions - If on different Docker networks, connect them (see Docker Setup)
- If Synapse is on a different host, ensure the URL is accessible and any firewalls allow traffic
Admin token endpoint returns 404 from nginx
Error: Diagnostics show "Admin API check failed" with an HTML 404 page from nginx.
Root cause: The Internal URL points to a public reverse proxy that does not forward /_synapse/admin/* paths to Synapse. This is normal — most reverse proxy setups intentionally block admin API access from the public internet.
Fix: Set the Internal URL to the direct Synapse address, not the public URL:
- Docker same network:
http://synapse:8008 - Same host:
http://localhost:8008 - By IP:
http://192.168.1.50:8008
Verify from inside the container:
curl -i http://synapse:8008/_synapse/admin/v1/registration_tokens \
-H "Authorization: Bearer YOUR_ADMIN_TOKEN"
If this returns JSON, use that URL as Internal URL. If it returns an HTML page, you're still hitting a proxy.
"Admin API not reachable" or 401 errors
Causes:
- Invalid admin access token
- Token belongs to a non-admin user
- Token has been invalidated
- Internal URL is wrong
Solutions:
- Verify the token works directly against the internal Synapse URL:
curl -H "Authorization: Bearer YOUR_TOKEN" \
http://synapse:8008/_synapse/admin/v1/registration_tokens - Ensure the user is a Synapse admin:
The response should show
curl -H "Authorization: Bearer YOUR_TOKEN" \
http://synapse:8008/_synapse/admin/v2/users/@admin:example.com"admin": true. - Generate a new token and rotate it in Admin → Servers → [Server] → Rotate Token
- Ensure Internal URL points to Synapse directly (not through a reverse proxy)
"Token registration not supported"
Error: Diagnostics show m.login.registration_token not found in flows.
Solution: Add to your homeserver.yaml:
enable_registration: true
registration_requires_token: true
Then restart Synapse.
"MSC3861 detected"
Error: Diagnostics warn about delegated authentication.
Explanation: If your Synapse uses OIDC/MAS (MSC3861), token-based registration is not available. The portal is incompatible with this authentication mode.
Solution: Use a Synapse instance without delegated authentication.
Registration
"The invitation code is invalid or has expired"
Causes:
- Token has been deleted or disabled
- Token has expired (
expiry_timein the past) - Token usage limit reached (
completed >= uses_allowed) - Token was created on a different server than the one being registered against
Solutions:
- Check token status in Admin → Tokens
- Create a new token if the existing one is expired/exhausted
- Verify the registration URL points to the correct server
"Registration is not permitted"
Cause: Synapse has enable_registration: false.
Solution: Set enable_registration: true in homeserver.yaml.
Username validation errors
The portal enforces Matrix localpart rules:
- Only lowercase letters, numbers, and
._=- - Maximum 255 characters
- Must not be already taken
- Must not be in a reserved namespace (e.g.,
@whatsapp_*for bridges)
Admin Authentication
Login succeeds but redirects back to login page
Symptom: You enter valid credentials, the login appears to succeed (no error), but you are immediately redirected back to the login page.
Root cause: The session cookie has the Secure flag set, but you are accessing the portal via plain HTTP. Browsers refuse to send Secure cookies over non-HTTPS connections.
Solutions:
- Set
APP_URLto your actual access URL (e.g.http://192.168.1.100:3000) - Or set
COOKIE_SECURE=falsein your.envfile - Or access the portal via HTTPS (recommended for production)
Diagnosis: Check docker compose logs app for:
[auth] Session check: no session cookie received
This confirms the browser is not sending the cookie.
Session expires immediately after login
Causes:
SESSION_SECRETchanged between login and the next request (container restart with a new random secret)- Cookie
pathmismatch (should be/)
Solutions:
- Ensure
SESSION_SECRETis set in.envand not randomly generated - Check logs for
[auth] Session config:to verify cookie settings
Login works locally but not behind reverse proxy
Causes:
- Proxy strips or does not forward cookies
APP_URLdoes not match the public URLSecurecookie enabled but proxy connects to the app via HTTP internally
Solutions:
- Set
APP_URLto the public HTTPS URL (e.g.https://invite.example.com) - Ensure proxy forwards
Host,X-Forwarded-For, andX-Forwarded-Protoheaders - If the proxy connects to the app via HTTP internally but provides HTTPS externally,
APP_URL=https://...is correct — the cookie will be Secure, and the browser will send it over HTTPS
Admin Dashboard
Server selector is empty
Cause: No servers have been added yet.
Solution: Go to Admin → Servers and add your first homeserver.
"No server selected" errors
Cause: The server context selector has no server selected, or the previously selected server was deleted.
Solution: Select a server from the dropdown in the admin sidebar.
Changes not reflected after server switch
Cause: The browser may have cached API responses.
Solution: Hard refresh the page (Ctrl+Shift+R / Cmd+Shift+R) or clear the server selection in the dropdown and re-select.
Branding
Uploaded images not showing
Causes:
- The
uploadsDocker volume is not mounted - File permissions issue
- Image was uploaded to a draft profile (not published)
Solutions:
- Verify the volume is mounted:
docker compose exec app ls /app/data/uploads/branding/ - Check file ownership:
docker compose exec app ls -la /app/data/uploads/branding/ - Publish the branding profile (Admin → Branding → Publish)
SVG upload rejected
By design: SVG files are blocked to prevent XSS attacks. Use PNG, JPEG, WebP, GIF, or ICO instead.
Docker Build
Prisma schema not found during build
Error: Could not find Prisma Schema during npm ci in Docker build.
Cause: The postinstall script runs prisma generate, which needs prisma/schema.prisma.
Solution: The Dockerfile copies the prisma directory before npm ci:
COPY prisma ./prisma
RUN npm ci
If you see this error, ensure your Dockerfile includes this COPY line.
Performance
Slow API responses
Causes:
- Synapse is under heavy load
- Database queries are slow
- Network latency between portal and Synapse
Solutions:
- Check Synapse health independently
- Add database indexes (Prisma schema already includes indexes on key columns)
- If Synapse is remote, consider running the portal closer to it
Rate limiting too aggressive
Solution: Increase the rate limit window or max requests in .env:
RATE_LIMIT_WINDOW_MS=1800000 # 30 minutes
RATE_LIMIT_MAX_REQUESTS=30 # 30 requests
Note: Rate limits are in-memory and reset on application restart.
Getting Help
- Check the Diagnostics page for automated health checks
- Review the Audit Log for recent errors
- Check container logs:
docker compose logs -f app - Open an issue on GitHub