Skip to content

Troubleshooting

Organized by area. Each entry: what you see → why → what to do.

Installation and startup

Backend exits: ENCRYPTION_KEY must be explicitly set when APP_ENV='production' Expected fail-fast. Set a valid Fernet key in .env (generation command is in the error message).

Backend exits: invalid format (not a valid Fernet key) Typo in ENCRYPTION_KEY. Regenerate; if data already exists under an old key, restore it, don't overwrite blindly.

password authentication failed for user "umbryx" on startup DB_PASSWORD changed after the PostgreSQL volume was initialized. Either restore the old password or reset the volume (docker compose down -v — destroys data).

App unreachable on :3000 docker compose ps for service states; check the published PORT and reverse-proxy forwarding.

Configuration

Sessions drop after every restart JWT_SECRET unset — auto-generated per start when persistence fails. Set it explicitly.

CORS errors after moving the UI to another origin Set CORS_ORIGINS to the UI origin (never *; credentials are in use).

WS behind a reverse proxy doesn't update live The /ws/ location needs HTTP/1.1 upgrade headers and long read timeouts (the shipped nginx configs show the working pattern). The frontend falls back to polling meanwhile.

Database and migrations

Migration error on startup Code/database version mismatch (e.g. DB restored from a newer backup). Restore matching versions or consciously alembic stamp <revision>.

Slow lists on huge projects Raise DATABASE_STATEMENT_TIMEOUT cautiously; prefer attaching a read replica (DATABASE_REPLICA_URL).

Authentication and authorization

401 everywhere after logout elsewhere Refresh tokens rotate on use and are blacklisted on logout (with Redis). Re-login.

403 on actions a role "should" be able to do Check the actual matrix — e.g. findings.approve belongs to reviewer only; credentials.read_secret to owner/admin/editor/ operator. See Access control.

First-run setup screen appears on an instance with users You are hitting a different database than you think (check DATABASE_URL / volume mounts) — setup only renders when the users table is empty.

Scans and execution

Scan fails: no attacker host / 404 on attacker_ssh No executor configured. Infra → Connections → add an attacker SSH target (or enable the executor flag on a pool workstation). The attacker_ssh module must be enabled.

No usable SSH credential found for attacker host The credential exists but isn't linked to that attacker host, or the host isn't marked attacker-side. Fix the linkage in Connections.

Job stuck in queued Worker pool exhausted or WORKER_BACKEND=arq without the worker service. Check System → Health and the worker badge in Jobs. Distinct from awaiting ROE approval, which needs an owner/admin to approve/reject.

Job fails: Blocked by ROE/scope guard Target outside scope or a forbidden activity/time window. Adjust ROE or scope; approval re-checks on approve.

Data and encryption

Cannot read encrypted value / decryption errors ENCRYPTION_KEY differs from the one that wrote the data. Restore the original key or re-encrypt via backend/scripts/rekey.py (dry-run first). Without the old key the data is unrecoverable.

Encrypted ZIP import asks for a password Exports containing credential secrets are AES-encrypted with a one-time password shown at export time. Lost password = re-export from the source instance.

Loot shows "No inline preview" Office/database formats are download-only by design. File decryption for preview is platform-admin gated.

Reports and limits

PDF button returns an HTML file WeasyPrint missing in that backend image — the server falls back to HTML. Install/enable the PDF-capable image.

429 Too Many Requests Built-in limits: report exports 10/min, login 5/min (plus account lockout), credential reveal 30/min, webhooks 120/min.

Licensing (EE)

402 on writes, banner about wind-down License expired past grace. Upload a renewed token (System → License); data and teardown remain available meanwhile.

Heartbeat logs License Server unreachable Network path to LICENSE_SERVER_URL blocked. Harmless until contract expiry; air-gapped installs should switch the channel to offline.

Token rejected on upload The token is bound to another installation's hardware/instance key — re-activation on a new host requires a new C2V round-trip.