pandas-dev/pandas · error · OptionError

Path prefix to option

Error message

Path prefix to option '{option}' is already an option

What it means

Raised by `register_option` inside the path-walk loop: for an intermediate segment `p` of the new key, the current `cursor` in `_global_config` is not a dict (it is already a scalar leaf value). That means an ancestor of the new key is itself a registered option, so the new nested key cannot be created. The message names the colliding ancestor via `path[:i]`.

Solutions

  1. Do not nest new keys under an existing leaf option; restructure so ancestors are namespaces, not values.
  2. If you control both keys, unregister/deprecate the leaf and re-register the hierarchy consistently.
  3. Choose a distinct top-level namespace for new options.

Example fix

# before
register_option('a.b', 1)
register_option('a.b.c', 2)   # OptionError: Path prefix ... is already an option

# after
register_option('a.b_core', 1)
register_option('a.b.c', 2)   # 'a.b' is now a namespace
Defensive patterns

Strategy: validation

Validate before calling

from pandas._config.config import _global_config, _registered_options
def parent_chain_is_namespace(key: str) -> bool:
    parts = key.split('.')
    cursor = _global_config
    for i, p in enumerate(parts[:-1]):
        if not isinstance(cursor, dict):
            return False
        if p in cursor:
            cursor = cursor[p]
        else:
            return True  # new namespace segment, fine
    return isinstance(cursor, dict)

Type guard

def key_is_nestable(key: str) -> bool:
    import pandas._config.config as c
    parts = key.split('.')
    cursor = c._global_config
    for p in parts[:-1]:
        if not isinstance(cursor, dict) or p not in cursor:
            return isinstance(cursor, dict)
        cursor = cursor[p]
    return isinstance(cursor, dict)

Try / catch

from pandas._config.config import OptionError
try:
    register_option(key, default)
except OptionError as e:
    if 'Path prefix' in str(e):
        # ancestor is a leaf; restructure keys and retry
        ...
    raise

Prevention

When it happens

Trigger: First `register_option('a.b', 1)` (so `a.b` is a leaf), then `register_option('a.b.c', 2)` — walking to `a.b` finds a scalar, not a dict.

Common situations: Designing a key hierarchy that nests below an already-registered leaf; refactoring option keys that introduce a parent/child inversion.

Related errors


AI-assisted analysis of pandas-dev/pandas@3b7651241d (2026-08-11). Data as JSON: /api/errors/1e4ea77db9684688. Report an issue: GitHub.

Appendix: source

Thrown at pandas/_config/config.py:583

    # the default value should be legal
    if validator:
        validator(defval)

    # walk the nested dict, creating dicts as needed along the path
    path = key.split(".")

    for k in path:
        if not re.match("^" + tokenize.Name + "$", k):
            raise ValueError(f"{k} is not a valid identifier")
        if keyword.iskeyword(k):
            raise ValueError(f"{k} is a python keyword")

    cursor = _global_config
    msg = "Path prefix to option '{option}' is already an option"

    for i, p in enumerate(path[:-1]):
        if not isinstance(cursor, dict):
            raise OptionError(msg.format(option=".".join(path[:i])))
        if p not in cursor:
            cursor[p] = {}
        cursor = cursor[p]

    if not isinstance(cursor, dict):
        raise OptionError(msg.format(option=".".join(path[:-1])))

    # a namespace already lives here, i.e. `key` is a path prefix to one or
    # more already-registered options; registering it would clobber them
    # (GH#29242)
    if isinstance(cursor.get(path[-1]), dict):
        raise OptionError(f"Option '{key}' is a prefix of an already-registered option")

    cursor[path[-1]] = defval  # initialize

    # save the option metadata
    _registered_options[key] = RegisteredOption(
        key=key, defval=defval, doc=doc, validator=validator, cb=cb

View on GitHub (pinned to 3b7651241d)