Skip to content
Latchkey

Django "The SECRET_KEY setting must not be empty" in CI

Django raises this the moment any signing or session code needs SECRET_KEY and it is empty. In CI the settings file usually reads it from os.environ, and that variable was never exposed to the job as a secret.

What this error means

Startup, tests, or manage.py check fail with "django.core.exceptions.ImproperlyConfigured: The SECRET_KEY setting must not be empty." The same code runs locally because a .env supplies the value.

Django
django.core.exceptions.ImproperlyConfigured: The SECRET_KEY setting must not be empty.

Common causes

The env var is not injected into CI

Settings do SECRET_KEY = os.environ["SECRET_KEY"] (or os.environ.get), but the workflow never sets it, so it resolves to empty.

A local .env that CI does not have

Development loads SECRET_KEY from an untracked .env. That file is not in the runner, so the value is blank.

How to fix it

Provide a SECRET_KEY as a CI secret

  1. Store a real key as a repository or environment secret.
  2. Expose it to the step env as SECRET_KEY.
  3. Never commit a production key; a CI-only value is fine for test runs.
.github/workflows/ci.yml
env:
  SECRET_KEY: ${{ secrets.DJANGO_SECRET_KEY }}

Generate a throwaway key for test-only jobs

When tests never sign anything meaningful, a per-run key is acceptable and keeps the job self-contained.

Terminal
export SECRET_KEY=$(python -c "from django.core.management.utils import get_random_secret_key; print(get_random_secret_key())")

How to prevent it

  • Read secrets from env vars and inject them via CI secrets, not committed files.
  • Fail fast: keep SECRET_KEY required so a missing value surfaces immediately.
  • Use a dedicated CI settings module that documents every required env var.

Related guides

Tired of flaky CI? Latchkey auto-heals failed jobs and retries them for you. Start free →