skip to content

A Django project fails at startup with AppRegistryNotReady: Apps aren't loaded yet. What typically causes it, and how do you fix it?

level: seniorimportance: should knowfreq 38%

answer

  1. something touched models too early
  2. three loading phases
  3. app __init__ and apps.py imports
  4. standalone scripts need setup
  5. gettext versus gettext_lazy

basics

~20 s

AppRegistryNotReady means code needed the app registry before django.setup() finished: models imported from an app's init.py or apps.py, a script that skipped django.setup(), or non-lazy gettext at import time. Defer the import or call setup first.

solid answer

~40 s

The registry loads in three phases: app configs, then every `models` module, then `ready()`. `AppRegistryNotReady` fires when code needs a later phase too early. **"Apps aren't loaded yet"** usually means a model was imported during phase one — from an app's `__init__.py`, from the top of `apps.py`, or indirectly through a helper module those import — or that a standalone script imported models without calling `django.setup()`. **"Models aren't loaded yet"** means code asked for model machinery during phase two, such as an ORM query at import time in a models module. Translation raises its own variant for a non-lazy `gettext()` at import time; use `gettext_lazy`. Fixes: keep app packages and `apps.py` free of model imports, move wiring into `ready()`, defer work into functions, and call `django.setup()` in scripts.

code

python · 11 lines
python
# scripts/export_patients.py - a standalone script
import os

import django

os.environ.setdefault("DJANGO_SETTINGS_MODULE", "clinic.settings")
django.setup()  # populate the app registry before touching models

from patients.models import Patient  # noqa: E402

print(Patient.objects.count())

go deeper

for a junior

Know that plain scripts must call django.setup() before importing models, or should be written as management commands instead.

for a middle

Explain the three loading phases and why importing models from an app's init.py or apps.py raises the error.

for a senior

Trace the traceback to the premature import, fix it with ready(), deferred functions or gettext_lazy, and reject reorder-until-it-works fixes.

for a principal

Set import-hygiene rules for app packages across teams so new modules never create load-order coupling in a large monolith.

## What the error means `django.core.exceptions.AppRegistryNotReady` is raised when code asks the app registry for something it has not finished loading. `django.setup()` populates the registry in three phases, walking `INSTALLED_APPS` in order each time: 1. **Apps** — create each `AppConfig` and import each app's root package. Afterwards `apps.get_app_config()` works. 2. **Models** — import each app's `models` submodule. Afterwards `apps.get_model()` works. 3. **Ready** — run each `AppConfig.ready()`. The registry raises `AppRegistryNotReady("Apps aren't loaded yet.")` if phase one is incomplete and `AppRegistryNotReady("Models aren't loaded yet.")` if phase two is. ## Typical causes on a clinic-booking monolith | Symptom | Cause | Fix | |---|---|---| | "Apps aren't loaded yet" at startup | `scheduling/__init__.py` does `from .models import Appointment` for convenience | remove model imports from app packages and `apps.py` | | same, only in one app | `apps.py` imports a `signals` module at top level, which imports models | import `signals` inside `ready()` | | same, in a cron script | a script imports `patients.models` without calling `django.setup()` | call `django.setup()` first, or write a management command | | "Models aren't loaded yet" | a models module runs an ORM query at import time | move the query into a function called later | | translation infrastructure error | `gettext("Booked")` at module level in a models or forms module | use `gettext_lazy` | When a standalone script has not configured settings at all, it fails even earlier with `ImproperlyConfigured` about unconfigured settings; setting `DJANGO_SETTINGS_MODULE` then leads to the registry error if `django.setup()` is still missing. ## Why model imports in phase one fail Creating a model class asks the registry which installed app contains its module. During phase one the registry is not ready to answer, so the class definition itself raises. The docs are blunt: during this stage "your code shouldn't import any models!" — not directly, and not indirectly through a helper module. ## A related registry error If a model's module belongs to no installed app, Django raises `RuntimeError: Model class patients.models.Patient doesn't declare an explicit app_label and isn't in an application in INSTALLED_APPS.` The usual causes are a forgotten `INSTALLED_APPS` entry or importing models through the wrong package path. ## How to fix it systematically 1. **Read the traceback bottom-up** until you reach your own module; that import is the one running too early. 2. **Keep app root packages and `apps.py` import-light**: no models, no forms, no modules that pull either in. 3. **Move wiring into `ready()`**, where all models are loaded. 4. **Defer work into functions**, evaluated on first use rather than at import — the docs call this lazy evaluation. 5. **Use lazy translation** (`gettext_lazy`) for strings defined at import time. 6. **For scripts**, prefer a management command, which calls `django.setup()` for you; otherwise call it explicitly before importing models. ## Preventing it rather than fixing it Most teams hit this error once and then add a few rules to code review: - An app's `__init__.py` stays empty or contains only metadata. - `apps.py` imports nothing from the app except inside `ready()`. - Models modules never run queries or build querysets into lists at import time. - Module-level user-facing strings use `gettext_lazy`. - One-off scripts are written as management commands, so `django.setup()` is never forgotten. With those rules, adding a new app never changes whether startup succeeds, and `INSTALLED_APPS` order stays a matter of resource precedence rather than load-order survival. ## What an interviewer is listening for A senior candidate explains the three phases, maps each message to the phase that was incomplete, and fixes the import path rather than reordering `INSTALLED_APPS` until it happens to work.

  • Why is reordering INSTALLED_APPS a bad fix for this error?
    Moving an app earlier can make an early import happen after the app it needs is registered, so the error disappears by accident. The docs recommend not importing models during the first phase at all, to avoid needless constraints on `INSTALLED_APPS` order. The real fix is removing the premature import.
  • Why does a non-lazy gettext at import time break startup?
    Translation catalogs are gathered from every installed app's `locale` directory, which needs the app registry. Calling `gettext()` while a module is imported during loading asks for that too early. `gettext_lazy` defers the lookup until the string is used, which also makes it follow the active language per request.

saying these in an interview costs you the question

  • Fixes the error by shuffling INSTALLED_APPS until it disappears
  • Imports models in an app's __init__.py for convenience
  • Runs a plain script importing models without django.setup()
  • Uses gettext instead of gettext_lazy for module-level strings
  • Believes importing a model is always safe once settings exist