facebookresearch/detectron2 · error · KeyError
Trying to update key {key}, but {prefix} is not a config, bu
Error message
Trying to update key {key}, but {prefix} is not a config, but has type {type(v)}. What it means
apply_overrides/safe_update walks each dotted key's parent prefixes and requires every intermediate node to be an OmegaConf config (struct-like node). If an intermediate prefix selects a plain value (int, str, list), the key cannot be descended into and a KeyError is raised.
Source
Thrown at detectron2/config/lazy.py:340
Args:
cfg: an omegaconf config object
overrides: list of strings in the format of "a=b" to override configs.
See https://hydra.cc/docs/next/advanced/override_grammar/basic/
for syntax.
Returns:
the cfg object
"""
def safe_update(cfg, key, value):
parts = key.split(".")
for idx in range(1, len(parts)):
prefix = ".".join(parts[:idx])
v = OmegaConf.select(cfg, prefix, default=None)
if v is None:
break
if not OmegaConf.is_config(v):
raise KeyError(
f"Trying to update key {key}, but {prefix} "
f"is not a config, but has type {type(v)}."
)
OmegaConf.update(cfg, key, value, merge=True)
try:
from hydra.core.override_parser.overrides_parser import OverridesParser
has_hydra = True
except ImportError:
has_hydra = False
if has_hydra:
parser = OverridesParser.create()
overrides = parser.parse_overrides(overrides)
for o in overrides:
key = o.key_or_group
value = o.value()View on GitHub (pinned to a2f4a8771a)
Solutions
- Fix the override path to target the actual leaf key (e.g. 'model.backbone=50' if backbone itself is the depth)
- Restructure the config so intermediate nodes are mappings (backbone: {depth: 50})
- Load the correct config version that contains the nested structure implied by the override
Example fix
# before
cfg.model.backbone = 50
LazyConfig.apply_overrides(cfg, ["model.backbone.depth=101"])
# after
cfg.model.backbone = {"depth": 50}
LazyConfig.apply_overrides(cfg, ["model.backbone.depth=101"]) Defensive patterns
Strategy: validation
Validate before calling
from omegaconf import OmegaConf
def override_ok(cfg, key):
parts = key.split('.')
for i in range(1, len(parts)):
v = OmegaConf.select(cfg, '.'.join(parts[:i]), default=None)
if v is not None and not OmegaConf.is_config(v):
return False
return True
assert override_ok(cfg, 'model.backbone.depth') Type guard
def is_descendable(cfg, dotted_key: str) -> bool:
return override_ok(cfg, dotted_key) Try / catch
try:
LazyConfig.apply_overrides(cfg, [opt])
except KeyError as e:
if "is not a config" in str(e):
# target the leaf directly instead
LazyConfig.apply_overrides(cfg, [opt.rsplit('.', 1)[0] + '=' + new_leaf_value])
else:
raise Prevention
- Keep intermediate config nodes as mappings, never leaves
- Validate override paths against the loaded config before launching long jobs
- Print the config tree when overrides fail
When it happens
Trigger: Running with an override like 'model.backbone.depth=101' where cfg.model.backbone is already the integer 50 (a leaf), or overriding 'train.dataset.name=X' when train.dataset is a string.
Common situations: Hydra-style CLI overrides (--config-key=value) hitting configs where earlier nodes are leaves; overriding keys that only exist in a different config version; appending children to non-struct nodes.
Related errors
- deletion is not yet a supported override
- target of LazyCall must be a callable or defines a callable!
- Config file {filename} has syntax error!
- Relative import of directories is not allowed within config
- Cannot import from {cur_file_no_suffix}.
AI-assisted analysis of facebookresearch/detectron2@a2f4a8771a (2026-08-27).
Data as JSON: /api/errors/680c75e3b94f552a.
Report an issue: GitHub.