{"record":{"id":"0431e0168e9c8c49","repo":"xai-org/x-algorithm","slug":"register-task-generator-expects-a-taskgenerator-su","errorCode":null,"errorMessage":"register_task_generator expects a TaskGenerator subclass, got {cls!r}","messagePattern":"register_task_generator expects a TaskGenerator subclass, got (.+?)","errorType":"validation","errorClass":"TypeError","httpStatus":null,"severity":"error","filePath":"grox/core/generators/registry.py","lineNumber":9,"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)","sourceCodeStart":1,"sourceCodeEnd":27,"githubUrl":"https://github.com/xai-org/x-algorithm/blob/24c60942c5c5fdad3a6addffb4c6e6d2f228f04f/grox/core/generators/registry.py#L1-L27","documentation":"register_task_generator is a class decorator/registration function that only accepts classes deriving from TaskGenerator. It explicitly type-checks at runtime because decorators are easy to misapply to functions or instances. Passing anything that is not a TaskGenerator subclass raises TypeError.","triggerScenarios":"Using @register_task_generator on a plain function, an instance, or a class that doesn't inherit TaskGenerator; calling register_task_generator(TaskGenerator.some_function) or with an imported symbol that isn't the class you expected.","commonSituations":"Copy-pasting the decorator onto a helper function; refactoring a generator class into a factory function without removing the decorator; import shadowing where the decorated name resolves to a method or instance.","solutions":["Make the decorated object a class inheriting from TaskGenerator (or PriorityTaskGenerator-compatible base).","If you meant to register an instance factory, wrap it in a TaskGenerator subclass implementing _poll/from_config.","Check the decorator target isn't a function or already-instantiated object.","Verify imports: ensure the name under the decorator is the class itself."],"exampleFix":"# before\n@register_task_generator\ndef make_tasks(): ...\n\n# after\n@register_task_generator\nclass MyTaskGenerator(TaskGenerator):\n    TASK_GENERATOR_TYPE = \"my_tasks\"","handlingStrategy":"type-guard","validationCode":"from grox.core.generators.registry import register_task_generator\nfrom grox.core.generators.task_generator import TaskGenerator\n\nassert isinstance(MyGen, type) and issubclass(MyGen, TaskGenerator)\nregister_task_generator(MyGen)","typeGuard":"def is_task_generator_class(obj) -> bool:\n    return isinstance(obj, type) and issubclass(obj, TaskGenerator)","tryCatchPattern":"try:\n    register_task_generator(obj)\nexcept TypeError as e:\n    if \"TaskGenerator subclass\" in str(e):\n        raise TypeError(f\"{obj!r} must subclass TaskGenerator\") from e\n    raise","preventionTips":["Only apply @register_task_generator to class definitions inheriting TaskGenerator.","Static-type the decorator parameter so mypy catches misuse.","Avoid refactoring registered classes into plain functions."],"tags":["python","decorator","type-error","registry"],"backgroundTag":"invalid-decorator-argument","analyzedSha":"24c60942c5c5fdad3a6addffb4c6e6d2f228f04f","analyzedAt":"2026-08-28T11:40:14.686Z","schemaVersion":2},"datasetVersion":"2026-08-28T16:17:29.566Z"}