django/django · error · RuntimeError

%r declares more than one default AppConfig: %s.

Error message

%r declares more than one default AppConfig: %s.

What it means

Raised as RuntimeError inside AppConfig.create when an app's apps.py module defines more than one AppConfig subclass with the class attribute `default = True`. Django uses default=True to disambiguate when multiple AppConfig subclasses exist; having two is contradictory.

Source

Thrown at django/apps/config.py:147

                    if (
                        issubclass(candidate, cls)
                        and candidate is not cls
                        and getattr(candidate, "default", True)
                    )
                ]
                if len(app_configs) == 1:
                    app_config_class = app_configs[0][1]
                else:
                    # Check if there's exactly one AppConfig subclass,
                    # among those that explicitly define default = True.
                    app_configs = [
                        (name, candidate)
                        for name, candidate in app_configs
                        if getattr(candidate, "default", False)
                    ]
                    if len(app_configs) > 1:
                        candidates = [repr(name) for name, _ in app_configs]
                        raise RuntimeError(
                            "%r declares more than one default AppConfig: "
                            "%s." % (mod_path, ", ".join(candidates))
                        )
                    elif len(app_configs) == 1:
                        app_config_class = app_configs[0][1]

            # Use the default app config class if we didn't find anything.
            if app_config_class is None:
                app_config_class = cls
                app_name = entry

        # If import_string succeeds, entry is an app config class.
        if app_config_class is None:
            try:
                app_config_class = import_string(entry)
            except Exception:
                pass
        # If both import_module and import_string failed, it means that entry

View on GitHub (pinned to ae25a40be0)

Solutions

  1. Inspect the named candidates in the error message and set `default = True` on exactly one of them (or none, if you reference the class explicitly in INSTALLED_APPS).
  2. Reference the desired AppConfig explicitly in INSTALLED_APPS via 'myapp.apps.MyAppConfig' and remove all default=True markers.

Example fix

# before — myapp/apps.py
class FooConfig(AppConfig):
    name = 'myapp'
    default = True
class BarConfig(AppConfig):
    name = 'myapp'
    default = True   # second default -> RuntimeError

# after — keep a single default
class FooConfig(AppConfig):
    name = 'myapp'
    default = True
class BarConfig(AppConfig):
    name = 'myapp'
    # default omitted (defaults to True; but only Foo is explicitly default=True -> chosen)
Defensive patterns

Strategy: validation

Validate before calling

import inspect
from django.apps import AppConfig
mod = import_module('myapp.apps')
defaults = [n for n, c in inspect.getmembers(mod, inspect.isclass)
            if issubclass(c, AppConfig) and c is not AppConfig and getattr(c, 'default', False)]
if len(defaults) > 1:
    raise ValueError(f'Multiple default AppConfigs in myapp.apps: {defaults}')

Type guard

import inspect
from django.apps import AppConfig

def has_single_default_appconfig(module) -> bool:
    defaults = [c for _, c in inspect.getmembers(module, inspect.isclass)
                if issubclass(c, AppConfig) and c is not AppConfig and getattr(c, 'default', False)]
    return len(defaults) <= 1

Try / catch

try:
    AppConfig.create('myapp')
except RuntimeError as e:
    if 'more than one default AppConfig' in str(e):
        # reference one AppConfig explicitly in INSTALLED_APPS
        raise SystemExit('Set INSTALLED_APPS=[\'myapp.apps.MyAppConfig\'] and clear default flags')
    raise

Prevention

When it happens

Trigger: module_has_submodule finds apps.py, more than one AppConfig subclass passes the default filter, then re-filtering by `default=True` (config.py:140-144) yields >1 candidate. Common after copy-paste of an AppConfig block.

Common situations: Refactoring where a developer adds a new AppConfig, marks it default=True but forgets to remove default=True from the old one; merging two app configs from different branches.

Related errors


AI-assisted analysis of django/django@ae25a40be0 (2026-08-06). Data as JSON: /api/errors/0c9b53cf0fedc3b4. Report an issue: GitHub.