pola-rs/polars · error · AttributeError

cannot override reserved namespace

Error message

cannot override reserved namespace {name!r}

What it means

The `pl.api.register_dataframe_namespace`-style `namespace()` decorator raises AttributeError if the chosen namespace name collides with one of Polars' reserved built-in namespaces (such as 'str', 'dt', 'cat', 'name', 'bin'). Reserved namespaces are core functionality and cannot be shadowed by user extensions. The check happens at decoration time, before any instances are created.

Solutions

  1. Pick a non-reserved namespace name (e.g. "mystr", "custom_str") and re-run the registration
  2. Check `polars.api` docs / `_reserved_namespaces` for the list of taken names

Example fix

// before
@pl.api.register_dataframe_namespace("str")
class MyStrNamespace: ...
// after
@pl.api.register_dataframe_namespace("my_str")
class MyStrNamespace: ...
Defensive patterns

Strategy: validation

Validate before calling

RESERVED = {'str','dt','cat','name','bin'}
assert ns_name not in RESERVED, f"{ns_name!r} is a reserved polars namespace"

Try / catch

try:
    pl.api.register_dataframe_namespace("str")(MyNS)
except AttributeError as e:
    if "reserved namespace" in str(e):
        ns_name = "my_str"
        pl.api.register_dataframe_namespace(ns_name)(MyNS)
    else:
        raise

Prevention

When it happens

Trigger: Decorating a custom namespace class whose `name` argument equals a reserved namespace, e.g. `@pl.api.register_dataframe_namespace("str")`, then applying it.

Common situations: Choosing a generic short name for a custom namespace that happens to match a built-in; copying example code and renaming the namespace to something already taken.

Related errors


AI-assisted analysis of pola-rs/polars@fe841f959e (2026-09-18). Data as JSON: /api/errors/4814e66354e3e9a1. Report an issue: GitHub.

Appendix: source

Thrown at py-polars/src/polars/api.py:56

    def __get__(self, instance: NS | None, cls: type[NS]) -> NS | type[NS]:
        if instance is None:
            return self._ns

        ns_instance = self._ns(instance)  # type: ignore[call-arg]
        setattr(instance, self._accessor, ns_instance)
        return ns_instance


def _create_namespace(
    name: str, cls: type[Expr | DataFrame | LazyFrame | Series]
) -> Callable[[type[NS]], type[NS]]:
    """Register custom namespace against the underlying Polars class."""

    def namespace(ns_class: type[NS]) -> type[NS]:
        if name in _reserved_namespaces:
            msg = f"cannot override reserved namespace {name!r}"
            raise AttributeError(msg)
        elif (attr := getattr(cls, name, None)) is not None:
            if isfunction(attr) or isinstance(attr, property) or name.startswith("_"):
                msg = f"cannot override `{cls.__name__}.{name}` with custom namespace {ns_class.__name__!r}"
                raise AttributeError(msg)
            warn(
                f"overriding existing custom namespace {name!r} (on {cls.__name__})",
                UserWarning,
                stacklevel=find_stacklevel(),
            )

        setattr(cls, name, NameSpace(name, ns_class))
        cls._accessors.add(name)
        return ns_class

    return namespace


def register_expr_namespace(name: str) -> Callable[[type[NS]], type[NS]]:

View on GitHub (pinned to fe841f959e)