pola-rs/polars · error · ValueError
extension type '{ext_name}' is already registered
Error message
extension type '{ext_name}' is already registered What it means
polars' extension-type registry is process-global, and register_extension_type refuses duplicate names: registering an ext_name already present in _REGISTRY raises ValueError. A second registration of the same name — even from re-imported or re-executed code — trips it.
Source
Thrown at py-polars/src/polars/datatypes/extension.py:30
@unstable()
def register_extension_type(
ext_name: str,
ext_class: type[dt.BaseExtension] | None = None,
*,
as_storage: bool = False,
) -> None:
"""
Register the extension type for the given extension name.
.. warning::
This functionality is currently considered **unstable**. It may be
changed at any point without it being considered a breaking change.
"""
if "ext_name" in _REGISTRY:
msg = f"extension type '{ext_name}' is already registered"
raise ValueError(msg)
if as_storage:
assert ext_class is None, "cannot specify ext_class when as_storage is True"
_REGISTRY[ext_name] = "storage"
with contextlib.suppress(NameError): # _plr module may be unavailable
_register_extension_type(ext_name, None)
else:
assert not as_storage, "as_storage must be False when ext_class is provided"
assert isinstance(ext_class, type)
assert issubclass(ext_class, dt.BaseExtension)
_REGISTRY[ext_name] = ext_class
with contextlib.suppress(NameError): # _plr module may be unavailable
_register_extension_type(ext_name, ext_class)
@unstable()
def unregister_extension_type(ext_name: str) -> None:
"""View on GitHub (pinned to df599052da)
Solutions
- Unregister first: polars.datatypes.extension.unregister_extension_type('my_ext'), then re-register
- Register once at module import and never re-run that code; in notebooks, guard the cell or track registration state
- In tests, use a fixture that unregisters in teardown (try/finally) so each test starts clean
Example fix
# before
register_extension_type('my_ext', MyExtDtype) # second call: ValueError
# after
from polars.datatypes.extension import register_extension_type, unregister_extension_type
try:
unregister_extension_type('my_ext')
except Exception:
pass
register_extension_type('my_ext', MyExtDtype) Defensive patterns
Strategy: validation
Validate before calling
from polars.datatypes.extension import register_extension_type, unregister_extension_type
def register_once(ext_name: str, ext_class=None, **kw) -> None:
try:
unregister_extension_type(ext_name)
except Exception:
pass # not registered yet
register_extension_type(ext_name, ext_class, **kw)
register_once('my_ext', MyExtDtype) Try / catch
from polars.datatypes.extension import register_extension_type
try:
register_extension_type('my_ext', MyExtDtype)
except ValueError as e:
if 'already registered' in str(e):
pass # idempotent: already set up in this process
else:
raise Prevention
- Register extension types once at module import; never inside functions called repeatedly
- In notebooks, keep registration in a single cell and avoid re-running it
- In tests, unregister in teardown fixtures so each test starts clean
When it happens
Trigger: Calling polars.datatypes.extension.register_extension_type('my_ext', ...) twice in one process: re-running a notebook registration cell, importlib.reload of a module that registers at import time, or a library registered from two code paths.
Common situations: Jupyter workflows with re-executed cells or %autoreload; test suites that register per-test without teardown; plugins that register on import and get imported twice via different paths.
Related errors
AI-assisted analysis of pola-rs/polars@df599052da (2026-08-16).
Data as JSON: /api/errors/66a40a0c8934e66e.
Report an issue: GitHub.