headroomlabs-ai/headroom · error · ValueError

compressor {name!r} is already registered

Error message

compressor {name!r} is already registered

What it means

Raised by CompressorRegistry.register when the name is already present and replace=False (the default). The registry deliberately makes double registration loud — two compressors under one name would silently change routing — so the second registration is refused unless the caller explicitly opts in with replace=True.

Source

Thrown at headroom/transforms/compressor_registry.py:186

        """Register ``compressor`` under its ``descriptor.name``.

        Args:
            compressor: The compressor to register.
            replace: If ``True``, replace an existing registration of the same
                name instead of raising.

        Returns:
            The registered name.

        Raises:
            ValueError: If the name is empty, or already registered and
                ``replace`` is ``False``.
        """
        name = compressor.descriptor.name
        if not name:
            raise ValueError("compressor descriptor.name must be non-empty")
        if name in self._compressors and not replace:
            raise ValueError(f"compressor {name!r} is already registered")
        self._compressors[name] = compressor
        return name

    def get(self, name: str) -> Compressor | None:
        """Return the registered compressor named ``name``, or ``None``."""
        return self._compressors.get(name)

    def names(self) -> list[str]:
        """Return all registered compressor names, sorted."""
        return sorted(self._compressors)

    def descriptors(self) -> list[CompressorDescriptor]:
        """Return the descriptors of all registered compressors, sorted by name."""
        return [self._compressors[n].descriptor for n in sorted(self._compressors)]

    def discover(self, *, replace: bool = False) -> list[str]:
        """Load and register compressors from the ``headroom.compressor`` group.

View on GitHub (pinned to 322425c43b)

Solutions

  1. If re-registration is intentional, call register(compressor, replace=True).
  2. Otherwise rename the new compressor's descriptor.name to something unique.
  3. Guard module-level registration with an idempotency check: if reg.get(name) is None: reg.register(...).

Example fix

# before
reg.register(my_compressor)  # second call -> ValueError

# after
if reg.get(my_compressor.descriptor.name) is None:
    reg.register(my_compressor)
# or explicit: reg.register(my_compressor, replace=True)
Defensive patterns

Strategy: try-catch

Validate before calling

if reg.get(compressor.descriptor.name) is None:
    reg.register(compressor)
else:
    reg.register(compressor, replace=True)  # if re-registration is intended

Try / catch

try:
    reg.register(compressor)
except ValueError as e:
    if "already registered" in str(e):
        reg.register(compressor, replace=True)
    else:
        raise

Prevention

When it happens

Trigger: Calling register(compressor) twice with the same descriptor.name, or registering a new compressor whose name collides with a built-in; e.g. plugin init running twice, or two modules registering the same name.

Common situations: A plugin and a built-in sharing a name; hot-reload re-executing registration code; a copy-pasted descriptor in tests; double import of a registration module under different names.

Related errors


AI-assisted analysis of headroomlabs-ai/headroom@322425c43b (2026-08-15). Data as JSON: /api/errors/20c3a5ac412af7a9. Report an issue: GitHub.