Fix Django LookupError: No Installed App With Label
Fix the Django LookupError no installed app with label in production, migrations, and Celery: add the app to INSTALLED_APPS, use the right app label, load the correct settings module, and avoid model imports before Django is ready.
Problem statement
A command or request fails with:
LookupError: No installed app with label 'billing'.
Sometimes with more context:
File ".../django/apps/registry.py", line 165, in get_app_config
raise LookupError(message)
LookupError: No installed app with label 'admin'.
Something asked Django's app registry for an app by its label, through apps.get_model("billing", "Invoice"), a migration dependency, a ForeignKey("billing.Invoice") string, or a management command such as migrate billing, and the registry has no app with that label. Either the app is not in INSTALLED_APPS for the settings this process loaded, or the label is different from what you think.
- Print the labels Django knows:
python manage.py shell -c "from django.apps import apps; print(sorted(a.label for a in apps.get_app_configs()))". - If the app is missing, add it to
INSTALLED_APPSin the settings used by this environment. - Check
DJANGO_SETTINGS_MODULE; production may load a settings file with a shorter app list. - Use the app label (the last part of the module name, or
AppConfig.label), not the full path. - For
'admin'errors, a third-party package or URL import needsdjango.contrib.admininstalled.
Step-by-step solution
1. List what the registry contains
Run the command in the failing context, for example inside the production container:
python manage.py shell -c "from django.apps import apps; print(sorted(a.label for a in apps.get_app_configs()))"
python manage.py diffsettings | grep -E "SETTINGS_MODULE|INSTALLED_APPS"
If billing is absent, the settings module did not include it. If something similar, such as billing_app, is present, the label differs.
2. Check which settings module is loaded
Split settings are the most common cause. INSTALLED_APPS in production.py may be a copy that drifted from base.py, or a deploy may set DJANGO_SETTINGS_MODULE to an old module:
# settings/production.py, risky
INSTALLED_APPS = ["django.contrib.admin", ..., "orders"] # forgot billing
# better: extend instead of redefine
from .base import * # noqa
INSTALLED_APPS += ["storages"]
Define the full list once in base.py and only append in environment files.
3. Use the correct label
The label defaults to the last component of the app module. For apps.billing, the label is billing, not apps.billing. A custom AppConfig can override it:
class BillingConfig(AppConfig):
name = "apps.billing"
label = "invoicing"
Now model references and migration dependencies must use invoicing. Changing a label on an existing app also renames its tables (invoicing_invoice) and its migration history, so never change it casually.
4. Remove references to apps you uninstalled
If you removed an app from INSTALLED_APPS, old migrations in other apps may still depend on it, or call apps.get_model("oldapp", ...) in a RunPython. Leave the app installed until its references are squashed away, or edit the old migrations to drop the dependency when nothing else needs it. Data migrations should look models up defensively when the app is optional.
5. Do not import models too early
Importing models at module level in a file loaded during settings, such as a custom storage class or a logging filter referenced from settings, runs before the registry is ready. That usually raises AppRegistryNotReady, but code that calls apps.get_app_config() early can raise LookupError instead. Move imports inside functions. See Fix Django AppRegistryNotReady in Celery and Scripts.
Explanation
Django's AppRegistry maps labels to AppConfig objects when django.setup() runs. Every string reference to a model, like "billing.Invoice", is resolved through that map. The registry knows nothing about apps that exist on disk but are not listed, which is why a perfectly importable package still produces LookupError. Because the list comes from settings, the error is almost always about which settings module a process uses, not about the code itself.
Edge cases / notes
- Celery workers. A worker started without
DJANGO_SETTINGS_MODULEmay fall back to a default incelery.pythat points at development settings. - Tests. Test settings that trim
INSTALLED_APPSfor speed can break migrations that depend on removed apps. - Duplicate labels. Two apps with the same label raise
ImproperlyConfigured: Application labels aren't uniqueinstead.
Next steps
- Clean up settings structure with Split Django Settings for Development and Production.
- For missing migration files, see Fix Django NodeNotFoundError.
- For early model imports, read Fix Django AppRegistryNotReady.
FAQ
What is an app label?
A short unique name for an app, by default the last part of its Python path. It is used in model references, migration names, and table names.
Why does migrate say No installed app with label?
migrate billing uses the label. If the app is not installed in the active settings or has another label, the command cannot find it.
Can I rename an app label?
Only with care. Table names and migration records include the label, so renaming needs migrations that rename tables and update django_migrations.
Why does it mention admin when I do not use it?
A package or your URL configuration imports admin features, which require django.contrib.admin in INSTALLED_APPS.