authx-identity / Runbooks / DjangoPlay + AuthX Troubleshooting
DocsAuthx-IdentityRunbooksDjangoPlay + AuthX Troubleshooting

DjangoPlay + AuthX Troubleshooting

Covers signup/auth failures across the AuthX identity service, its Postgres database. Local runs via DockerCompose; production runs via systemd (no Docker). Commands differ accordingly — each secti...

6 min readApplies to v1.1.1
On this page ▾
  1. 1. Diagnostic order
  2. 2. Service status & logs
  3. Local (Docker Compose)
  4. Production (systemd)
  5. 3. DNS resolution failure (socket.gaierror)
  6. 4. Password authentication failure (InvalidPasswordError)
  7. 5. Missing schema (UndefinedTableError: relation "user_identity" does not exist)
  8. 6. App-level signup failure after AuthX/DB look healthy
  9. 7. Quick reference — command differences at a glance

1. Diagnostic order

When signup/login is broken, check in this order — each layer's errors look different and point to a different fix:

  1. DNS resolution (socket.gaierror / Temporary failure in name resolution) → wrong hostname in DATABASE_URL.
  2. Password auth (InvalidPasswordError) → role/DB password mismatch.
  3. Missing schema (UndefinedTableError: relation "user_identity" does not exist) → migrations never ran against this database.
  4. App-level 500s after DB looks healthy → check DjangoPlay's own logs, not AuthX's.
  5. Wrong domain in a generated link (404 on a real path) → SITE_URL/ subdomain config, not a service crash.

2. Service status & logs

Local (Docker Compose)

bash
docker compose ps
docker compose logs authx -f
docker compose logs db -f
docker compose exec authx sh -c 'env | grep DATABASE_URL'

Production (systemd)

bash
sudo systemctl status djangoplay djangoplay-celery.service authx-identity.service --no-pager -l
sudo journalctl -u authx-identity.service --since "15 min ago" --no-pager -o cat
sudo journalctl -u djangoplay.service --since "15 min ago" --no-pager -o cat

3. DNS resolution failure (socket.gaierror)

Symptom: asyncpg.exceptions traceback ending in socket.gaierror: [Errno -3] Temporary failure in name resolution.

Cause: the host in DATABASE_URL / DATABASE_URL_SYNC doesn't resolve in this environment. The correct hostname is different between the two environments — this is the single biggest source of confusion:

Environment Correct host Why
Prod (systemd, bare metal) 127.0.0.1 Postgres runs locally via systemd; there's no Docker network to resolve a service name against.
Local (Docker Compose), from the authx container db Docker Compose's internal DNS resolves service names between sibling containers. 127.0.0.1 inside a container means itself, not the db container.
Local, from your host shell (e.g. running authx-migrate directly, outside Docker) 127.0.0.1, port from the db service's host-mapped port (e.g. 5433, per docker-compose.yml's ports:) — not the container-internal 5432. You're not inside the Docker network here.

Fix:

bash
# check current value
sudo cat /opt/djangoplay/.dplay/.authx | grep DATABASE_URL      # prod
cat .env | grep DATABASE_URL                                     # local

# confirm it resolves (prod) — empty output = confirmed broken
getent hosts <hostname>

# fix to the correct host per the table above, then restart:
sudo systemctl restart authx-identity.service                    # prod
docker compose up --build -d                                     # local

4. Password authentication failure (InvalidPasswordError)

Symptom: asyncpg.exceptions.InvalidPasswordError: password authentication failed for user "authx".

Cause: whatever password is stored in Postgres for the authx role doesn't match what's in DATABASE_URL. This is not the same as the password "looking correct" in a config file — only a live connection test confirms it.

Isolate it — test the password directly, independent of the app:

bash
# prod
sudo -u postgres psql -h 127.0.0.1 -U authx -d authx

# local
docker compose exec db psql -U authx -d authx

If this fails with the password you believe is correct, Postgres itself needs updating — a visual match against a config file is not sufficient proof.

Fix — prod (persistent role, reset in place):

bash
sudo -u postgres psql -c "ALTER ROLE authx WITH PASSWORD '<exact password from .authx>';"

If the password contains ' \ ` $or backslashes, don't pass it inline with-c— write it to a.sqlfile and run withpsql -f` so the shell doesn't mangle it.

Fix — local (Docker, throwaway data):

bash
# fastest: wipe and reinit from .env's POSTGRES_PASSWORD
docker compose down -v
docker compose up --build -d

# OR, without losing data:
docker compose exec db psql -U authx -d authx -c "ALTER ROLE authx WITH PASSWORD '<matches .env>';"

Common trap (local only): Postgres init scripts (which apply POSTGRES_PASSWORD) only run once, on first creation of an empty data volume. Editing .env after the authx_postgres_data volume already exists does nothing until the volume is recreated (down -v) or the role is altered manually.

Common trap (either environment): running psql with no -h/-p flags may silently connect to an unrelated local Postgres instance (e.g. a different local database, or a native install on your machine) instead of the one you're trying to test. Always be explicit: -h 127.0.0.1 and the correct port.


5. Missing schema (UndefinedTableError: relation "user_identity" does not exist)

Symptom: password/connection succeeds, but queries fail with relation "user_identity" does not exist (or refresh_token).

Cause: migrations have never been applied to this database.

Fix — prod / anywhere installed via pip install authx-identity:

bash
set -a; source /opt/djangoplay/.dplay/.authx; set +a
/opt/djangoplay/app/djangoplay-web/.venv/bin/authx-migrate upgrade

authx-migrate ships inside the installed package (as of 1.1.1) — no source checkout of the AuthX repo is needed. It reads DATABASE_URL_SYNC from the environment, so the env vars must be loaded into the shell first — authx-migrate does not know about .authx or .env by name, it just reads os.environ (or a file literally named .env in the current directory).

Fix — local (Docker): migrations already run automatically as part of the authx service's startup command (alembic upgrade head && uvicorn ... in docker-compose.yml). If tables are still missing after a successful docker compose up, check docker compose logs authx for a migration error rather than assuming it needs to be run manually.

Verify tables exist:

bash
sudo -u postgres psql -d authx -c "\dt"        # prod
docker compose exec db psql -U authx -d authx -c "\dt"   # local

If authx-migrate itself fails with a Pydantic ValidationError listing every field as "Field required": the env vars weren't loaded into the shell before running the command. This is unrelated to Docker — it happens identically on bare metal. Always run:

bash
set -a; source <path-to-your-env-file>; set +a
authx-migrate upgrade

from a shell where that file actually exists, before invoking the command.


6. App-level signup failure after AuthX/DB look healthy

Check DjangoPlay's own logs, not AuthX's — the request may be failing somewhere else in the chain (rate limiting, DB write on the Django side, etc.):

bash
sudo journalctl -u djangoplay.service --since "15 min ago" --no-pager -o cat | grep manual_signup   # prod
docker compose logs djangoplay -f   # if djangoplay itself runs in Docker locally

Look for users.views.ui.manual_signup log lines — Manual signup failed unexpectedly with no further detail means the actual exception is in the authx-identity logs (section 2), not here.


7. Quick reference — command differences at a glance

Task Local (Docker Compose) Production (systemd)
View service logs docker compose logs authx -f sudo journalctl -u authx-identity.service -f
Restart AuthX docker compose up --build -d sudo systemctl restart authx-identity.service
Correct DB host in DATABASE_URL db (Compose service name) 127.0.0.1
Connect to Postgres directly docker compose exec db psql -U authx -d authx sudo -u postgres psql -h 127.0.0.1 -U authx -d authx
Reset a stuck/mismatched password docker compose down -v && docker compose up --build -d (wipes local volume) sudo -u postgres psql -c "ALTER ROLE authx WITH PASSWORD '...';"
Run migrations Automatic on container start (alembic upgrade head in the compose command) authx-migrate upgrade (after sourcing .authx into the shell)
Load env vars into a shell for manual commands Not usually needed — env_file: .env is loaded automatically for containers set -a; source /opt/djangoplay/.dplay/.authx; set +a