celery/celery · critical · ImproperlyConfigured
Cannot mix new and old setting keys, please rename the foll
Error message
Cannot mix new and old setting keys, please rename the
following settings to the new format:
{renames}
What it means
Raised in celery/app/utils.py:274 as ImproperlyConfigured when the user's settings simultaneously contain both new-style (lowercase, e.g. `task_serializer`) and old-style (UPPERCASE prefixed, e.g. `CELERY_TASK_SERIALIZER`) keys without a clean rename. Celery's Settings loader detects the mix, picks the majority namespace, and emits a rename suggestion list (`{renames}`). The message lists exactly which keys to rename. The guard prevents ambiguous/partial config where two keys collide.
Source
Thrown at celery/app/utils.py:274
info, left = _old_settings_info, is_in_new
if is_in_new and len(is_in_new) > len(is_in_old):
# Majority of the settings are new
info, left = _settings_info, is_in_old
else:
# no settings, just use new format.
info, left = _settings_info, is_in_old
if prefix:
# always use new format if prefix is used.
info, left = _settings_info, set()
# only raise error for keys that the user didn't provide two keys
# for (e.g., both ``result_expires`` and ``CELERY_TASK_RESULT_EXPIRES``).
really_left = {key for key in left if info.convert[key] not in have}
if really_left:
# user is mixing old/new, or new/old settings, give renaming
# suggestions.
raise ImproperlyConfigured(info.mix_error.format(renames='\n'.join(
FMT_REPLACE_SETTING.format(replace=key, with_=info.convert[key])
for key in sorted(really_left)
)))
preconf = {info.convert.get(k, k): v for k, v in preconf.items()}
defaults = dict(deepcopy(info.defaults), **preconf)
return Settings(
preconf, [conf, defaults],
(_old_key_to_new, _new_key_to_old),
deprecated_settings=is_in_old,
prefix=prefix,
)
class AppPickler:
"""Old application pickler/unpickler (< 3.1)."""
def __call__(self, cls, *args):View on GitHub (pinned to 3511be41db)
Solutions
- Read the `{renames}` list in the error message and rename every listed key to the suggested new name.
- Search the config (and env) for the exact old keys reported and remove/replace them.
- Use the `configuration_url`/new-format docs for your Celery version to verify all keys are lowercase new-style.
Example fix
// before CELERY_TASK_SERIALIZER = 'json' task_result_expires = 3600 // after task_serializer = 'json' task_result_expires = 3600
Defensive patterns
Strategy: validation
Validate before calling
OLD_PREFIX = 'CELERY_'
def check_settings(settings_dict):
mixed = [k for k in settings_dict if k.startswith(OLD_PREFIX)]
if mixed:
raise SystemExit(f'Remove/rename legacy settings: {mixed}') Type guard
def is_new_style_key(key: str) -> bool:
return not key.startswith('CELERY_') Try / catch
from celery.exceptions import ImproperlyConfigured
try:
app = Celery('proj', settings_source=...)
except ImproperlyConfigured as e:
# parse rename suggestions from the message and fix config
... Prevention
- Use only new-style lowercase keys (task_*, result_*, worker_*).
- Audit config during upgrades from Celery 3.x.
- Avoid copy-pasting settings from different Celery version docs.
When it happens
Trigger: A settings module that defines both `task_default_queue = 'q'` and `CELERY_DEFAULT_QUEUE = 'q2'`; copying config snippets from different Celery version docs; partial migration off the legacy uppercase format.
Common situations: Upgrading from Celery 3.x to 4+ (the big settings rename); mixing project-level new keys with a third-party package that still ships old keys; environment variables injecting old UPPERCASE names alongside new code.
Related errors
- ArangoDb backend settings should be grouped in a dict
- soft_time_limit must be less than or equal to time_limit
- fast_trace_task: worker task registry is empty (`_loc` was n
- Indexes start at 1 got: {ns_name!r}
- No node at index {ns_name!r}
AI-assisted analysis of celery/celery@3511be41db (2026-08-09).
Data as JSON: /api/errors/a6a33827b2e2d113.
Report an issue: GitHub.