## TL;DR
Run `migrate` with no app label before anything else touches the database, and check that the database user can create tables. On a truly fresh database, django_migrations is created by the very first migrate run, so this error means something ran SQL before migrations ever ran, or migrate is pointed at the wrong database.

```text
django.db.utils.ProgrammingError: relation "django_migrations" does not exist
```

## Steps

1. Confirm the database is actually fresh. List its tables.
   Expected: no tables at all, or tables present but no django_migrations.

2. Run `python manage.py migrate` with no app arguments, before any other command touches the database.
   Expected: "Applying ..." lines scroll past and the django_migrations table is created.

3. If migrate itself errors, check the DATABASES setting points at the database you inspected, and that the database user has CREATE privileges.
   Expected: settings, database, and user all agree with each other.

4. If some other code ran first (a data script, a raw SQL runner, a health check that queries the DB), reorder the startup so migrate runs before anything else.
   Expected: migrate succeeds when it runs first.

5. Verify with `python manage.py showmigrations`.
   Expected: every migration listed as applied.

## Use this when
- A fresh database fails on missing django_migrations.
- Some script or health check ran before the first migrate.
- Tests fail while creating a new test database.
- Migrate seems to target a different database than the one you inspected.

## Not for this skill when
- django_migrations exists but is out of sync (that is a history-reconciliation problem).
- The error is a permission failure on existing tables.
- App tables are missing after a migrate that reported success.

## Variant phrasings
- relation django_migrations does not exist
- django migrate fresh database fails
- ProgrammingError django_migrations
- django_migrations table missing

## Why it happens
Django creates django_migrations during the first migrate run. If application code, a seed script, or a health check queries the database before migrate runs, or migrate is pointed at the wrong database, the table does not exist yet and anything touching it errors. The table is the symptom; the ordering is the disease.

## Edge cases
- Multiple databases each need their own run: `migrate --database=[name]`.
- Test runners create the table automatically. If it fails there, check the test database creation permissions, not the migrations.
- Database routers that send migrations to the wrong database cause this on the default one while the real one works fine.

## Provenance

Resolved from the public thread: https://vectle.com/posts/pst_vn7DJxJwQv-1K0rNLd9tvA
