{"record":{"id":"20c3a5ac412af7a9","repo":"headroomlabs-ai/headroom","slug":"compressor-name-r-is-already-registered","errorCode":null,"errorMessage":"compressor {name!r} is already registered","messagePattern":"compressor (.+?) is already registered","errorType":"exception","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"headroom/transforms/compressor_registry.py","lineNumber":186,"sourceCode":"        \"\"\"Register ``compressor`` under its ``descriptor.name``.\n\n        Args:\n            compressor: The compressor to register.\n            replace: If ``True``, replace an existing registration of the same\n                name instead of raising.\n\n        Returns:\n            The registered name.\n\n        Raises:\n            ValueError: If the name is empty, or already registered and\n                ``replace`` is ``False``.\n        \"\"\"\n        name = compressor.descriptor.name\n        if not name:\n            raise ValueError(\"compressor descriptor.name must be non-empty\")\n        if name in self._compressors and not replace:\n            raise ValueError(f\"compressor {name!r} is already registered\")\n        self._compressors[name] = compressor\n        return name\n\n    def get(self, name: str) -> Compressor | None:\n        \"\"\"Return the registered compressor named ``name``, or ``None``.\"\"\"\n        return self._compressors.get(name)\n\n    def names(self) -> list[str]:\n        \"\"\"Return all registered compressor names, sorted.\"\"\"\n        return sorted(self._compressors)\n\n    def descriptors(self) -> list[CompressorDescriptor]:\n        \"\"\"Return the descriptors of all registered compressors, sorted by name.\"\"\"\n        return [self._compressors[n].descriptor for n in sorted(self._compressors)]\n\n    def discover(self, *, replace: bool = False) -> list[str]:\n        \"\"\"Load and register compressors from the ``headroom.compressor`` group.\n","sourceCodeStart":168,"sourceCodeEnd":204,"githubUrl":"https://github.com/headroomlabs-ai/headroom/blob/322425c43bffde1ed0b64fecf3cf5951565dd82b/headroom/transforms/compressor_registry.py#L168-L204","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["If re-registration is intentional, call register(compressor, replace=True).","Otherwise rename the new compressor's descriptor.name to something unique.","Guard module-level registration with an idempotency check: if reg.get(name) is None: reg.register(...)."],"exampleFix":"# before\nreg.register(my_compressor)  # second call -> ValueError\n\n# after\nif reg.get(my_compressor.descriptor.name) is None:\n    reg.register(my_compressor)\n# or explicit: reg.register(my_compressor, replace=True)","handlingStrategy":"try-catch","validationCode":"if reg.get(compressor.descriptor.name) is None:\n    reg.register(compressor)\nelse:\n    reg.register(compressor, replace=True)  # if re-registration is intended","typeGuard":null,"tryCatchPattern":"try:\n    reg.register(compressor)\nexcept ValueError as e:\n    if \"already registered\" in str(e):\n        reg.register(compressor, replace=True)\n    else:\n        raise","preventionTips":["Make module-level registration idempotent (check reg.get first).","Use replace=True explicitly when overriding a built-in compressor.","Namespace plugin compressor names (e.g. 'myorg-foo') to avoid collisions."],"tags":["registry","duplicate","plugin"],"backgroundTag":null,"analyzedSha":"322425c43bffde1ed0b64fecf3cf5951565dd82b","analyzedAt":"2026-08-15T01:03:05.481Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}