Help Center
Troubleshooting

Troubleshooting

Server Starts but Registration or Login Returns 500

Symptoms: /api/v1/health returns {"status":"ok"}, but creating an account or any real request fails with an INTERNAL / 500 error. Logs mention a missing relation or table.

Cause: the database migrations were never applied. The health endpoint does not touch the schema, so the server can start and report healthy against an empty database. The server command does not auto-migrate.

Fix: apply the migrations, then retry:

# Full stack
docker compose exec -T vaultctl /usr/local/bin/vaultctl migrate up
 
# Simple compose
docker compose -f docker-compose.simple.yml exec -T vaultctl /usr/local/bin/vaultctl migrate up

The one-line installer does this for you. migrate up is idempotent — safe to re-run after every upgrade.


Installer Cannot Find or Start Docker (macOS)

Symptoms: the installer reports "Docker daemon is not running", or docker is not found on a fresh macOS machine.

  • Homebrew required: on macOS the installer uses Homebrew to install a headless runtime (colima + the docker CLI). Install Homebrew (opens in a new tab) first, then re-run.
  • Daemon not running: the installer runs colima start automatically. To do it manually:
    colima start
    docker info        # should now succeed
  • PATH: Homebrew installs to /usr/local/bin (Intel) or /opt/homebrew/bin (Apple Silicon). If docker is "not found" in a non-interactive shell, ensure that directory is on your PATH.
  • Docker Desktop: if you already run Docker Desktop, the installer uses it instead of colima — just make sure it is started.

Cannot Connect to Server

Symptoms: Browser shows "connection refused", "ERR_CONNECTION_TIMED_OUT", or "unable to reach server".

Check these in order:

  1. Server is running:

    docker compose ps
    # or
    systemctl status vaultctl
  2. Correct URL: Ensure you are using https:// (not http://) and the correct port. The default is 443 if behind a reverse proxy, or 8080 for the raw server.

  3. TLS certificate: If using a self-signed certificate, your browser may block the connection. Accept the certificate or configure a trusted CA.

  4. Firewall: Ensure the port is open:

    # Check if the port is listening
    ss -tlnp | grep 8080
  5. Reverse proxy: If using Caddy or nginx, check the proxy logs:

    docker compose logs caddy
    # or
    journalctl -u nginx

Login Fails

Symptoms: "Invalid credentials" error after entering correct password.

  • Caps Lock: Verify Caps Lock is off. The master password is case-sensitive.
  • Account locked: After 5 consecutive failed attempts, the account is locked for 15 minutes (configurable via LOCKOUT_DURATION). Wait and try again.
  • KDF mismatch: If you changed KDF parameters after registration (not recommended), the client may derive a different auth hash. Use the same parameters that were set during account creation.

If your account is locked, you will receive an ACCOUNT_LOCKED error. The lockout expires automatically — there is no manual unlock.


Slow Login

Symptoms: Login takes 2-5 seconds or more.

This is expected behavior. vaultctl uses Argon2id with 64 MB of memory and 3 iterations for key derivation. This is intentionally slow to make brute-force attacks impractical.

  • 2-5 seconds is normal on modern hardware.
  • Older or low-memory devices may take longer.
  • Do not reduce KDF parameters to speed up login — this weakens security.

Browser Extension Not Autofilling

Symptoms: The extension icon appears but does not fill in credentials.

  1. Check permissions: Ensure the extension has permission to access the current site. Click the extension icon and check site access settings.

  2. Check URI match: The extension matches saved items by URI. If the saved URI is https://example.com/login but you are on https://example.com/app/login, the match may fail. Edit the item and update the URI, or add multiple URIs.

  3. Multiple matches: If multiple items match, the extension shows a dropdown instead of autofilling. Click the extension icon and select the correct item.

  4. Iframe isolation: Some sites use iframes for login forms. The extension may not have access to iframe contents depending on browser security settings.


429 Rate Limited

Symptoms: API returns {"error": {"code": "RATE_LIMITED", "message": "too many requests"}}.

The server enforces rate limits to prevent abuse:

ScopeDefault Limit
Per IP60 requests/min
Per email (auth endpoints)5 attempts / 15 min

Resolution:

  • Wait for the Retry-After header value (in seconds) before retrying.
  • If you are hitting the per-IP limit from scripts or automation, increase RATE_LIMIT_RPM in the server configuration.
  • If you are hitting the per-email limit, wait 15 minutes or adjust AUTH_RATE_LIMIT_WINDOW.

500 Internal Server Error

Symptoms: API returns {"error": {"code": "INTERNAL", "message": "internal server error"}}.

  1. Check server logs:

    docker compose logs vaultctl --tail 100
    # or
    journalctl -u vaultctl --since "5 minutes ago"
  2. Database connectivity: Verify PostgreSQL is running and the DATABASE_URL is correct:

    docker compose exec db pg_isready
  3. Missing environment variables: Ensure all required env vars are set. See Server Configuration.

  4. Disk space: Check available disk space. PostgreSQL may refuse writes if the disk is full.

  5. Report the issue: If the error persists, open an issue on GitHub (opens in a new tab) with the relevant log output (redact any sensitive values).

⚠️

Server logs may contain request metadata. The LOG_REDACT_FIELDS environment variable controls which fields are redacted. Ensure sensitive fields are redacted before sharing logs publicly.