{"record":{"id":"64340ba553990f30","repo":"xai-org/x-algorithm","slug":"duplicate-generator-registration-for-key-r-exi","errorCode":null,"errorMessage":"Duplicate generator registration for {key!r}: {existing.__name__} vs {cls.__name__}","messagePattern":"Duplicate generator registration for (.+?): (.+?) vs (.+?)","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"grox/core/generators/registry.py","lineNumber":19,"sourceCode":"from grox.config.config import TaskGeneratorConfig\nfrom grox.core.generators.task_generator import TaskGenerator\n\n_REGISTRY: dict[str, type[TaskGenerator]] = {}\n\n\ndef register_task_generator(cls: type[TaskGenerator]) -> type[TaskGenerator]:\n    if not (isinstance(cls, type) and issubclass(cls, TaskGenerator)):\n        raise TypeError(\n            f\"register_task_generator expects a TaskGenerator subclass, got {cls!r}\"\n        )\n    if not cls.TASK_GENERATOR_TYPE:\n        raise ValueError(\n            f\"{cls.__name__} must set TASK_GENERATOR_TYPE to be registered\"\n        )\n    key = cls.TASK_GENERATOR_TYPE\n    existing = _REGISTRY.get(key)\n    if existing is not None and existing is not cls:\n        raise ValueError(\n            f\"Duplicate generator registration for {key!r}: {existing.__name__} vs {cls.__name__}\"\n        )\n    _REGISTRY[key] = cls\n    return cls\n\n\ndef build(cfg: TaskGeneratorConfig) -> TaskGenerator:\n    cls = _REGISTRY.get(cfg.type)\n    if cls is None:\n        raise ValueError(\n            f\"No task generator registered for type {cfg.type!r}. Registered: {sorted(_REGISTRY)}\"\n        )\n    return cls.from_config(cfg)\n\n\ndef registered_types() -> set[str]:\n    return set(_REGISTRY)\n","sourceCodeStart":1,"sourceCodeEnd":37,"githubUrl":"https://github.com/xai-org/x-algorithm/blob/24c60942c5c5fdad3a6addffb4c6e6d2f228f04f/grox/core/generators/registry.py#L1-L37","documentation":"The generator registry is keyed by TASK_GENERATOR_TYPE and refuses two different classes claiming the same key, because build() could not disambiguate which one to instantiate. Re-registering the exact same class is idempotent, but a second distinct class with the same type raises ValueError.","triggerScenarios":"Two TaskGenerator subclasses in the same process both set TASK_GENERATOR_TYPE to the same string; double imports of a module under different names (e.g. path + package import) creating distinct class objects; copy-pasted generator subclass that kept the parent's type constant.","commonSituations":"See trigger scenarios.","solutions":["Give the new generator a unique TASK_GENERATOR_TYPE value.","If the class was copy-pasted, rename its type constant.","If it's a re-register of the same logical class imported twice, normalize imports (single canonical module path) or guard with a registry check.","Deregister/reset the registry in test setups between suites."],"exampleFix":"# before\nclass GenA(TaskGenerator):\n    TASK_GENERATOR_TYPE = \"tasks\"\nclass GenB(TaskGenerator):\n    TASK_GENERATOR_TYPE = \"tasks\"  # duplicate\n\n# after\nclass GenB(TaskGenerator):\n    TASK_GENERATOR_TYPE = \"tasks_b\"","handlingStrategy":"validation","validationCode":"from grox.core.generators.registry import _REGISTRY\n\nif cls.TASK_GENERATOR_TYPE in _REGISTRY:\n    assert _REGISTRY[cls.TASK_GENERATOR_TYPE] is cls, \"duplicate type key\"","typeGuard":"def registration_is_unique(cls) -> bool:\n    from grox.core.generators.registry import _REGISTRY\n    existing = _REGISTRY.get(cls.TASK_GENERATOR_TYPE)\n    return existing is None or existing is cls","tryCatchPattern":"try:\n    register_task_generator(cls)\nexcept ValueError as e:\n    if \"Duplicate generator registration\" in str(e):\n        cls.TASK_GENERATOR_TYPE = f\"{cls.TASK_GENERATOR_TYPE}_{cls.__module__}\"\n        register_task_generator(cls)\n    else:\n        raise","preventionTips":["Generate TASK_GENERATOR_TYPE from the class name to guarantee uniqueness.","Import generator modules through a single canonical path.","Reset/clear the registry in test fixtures between suites."],"tags":["python","registry","duplicate-key","configuration"],"backgroundTag":"duplicate-registration-key","analyzedSha":"24c60942c5c5fdad3a6addffb4c6e6d2f228f04f","analyzedAt":"2026-08-28T11:40:14.686Z","schemaVersion":2},"datasetVersion":"2026-08-28T16:17:29.566Z"}