xai-org/x-algorithm · error · ValueError

{cls.__name__} must set TASK_GENERATOR_TYPE to be registered

Error message

{cls.__name__} must set TASK_GENERATOR_TYPE to be registered

What it means

Every TaskGenerator subclass must declare a non-empty TASK_GENERATOR_TYPE class attribute — it is the registry key used by build() to look up generators from config. register_task_generator refuses classes with a missing, None, or empty TASK_GENERATOR_TYPE so the registry stays keyed by meaningful names.

Source

Thrown at grox/core/generators/registry.py:13

from grox.config.config import TaskGeneratorConfig
from grox.core.generators.task_generator import TaskGenerator

_REGISTRY: dict[str, type[TaskGenerator]] = {}


def register_task_generator(cls: type[TaskGenerator]) -> type[TaskGenerator]:
    if not (isinstance(cls, type) and issubclass(cls, TaskGenerator)):
        raise TypeError(
            f"register_task_generator expects a TaskGenerator subclass, got {cls!r}"
        )
    if not cls.TASK_GENERATOR_TYPE:
        raise ValueError(
            f"{cls.__name__} must set TASK_GENERATOR_TYPE to be registered"
        )
    key = cls.TASK_GENERATOR_TYPE
    existing = _REGISTRY.get(key)
    if existing is not None and existing is not cls:
        raise ValueError(
            f"Duplicate generator registration for {key!r}: {existing.__name__} vs {cls.__name__}"
        )
    _REGISTRY[key] = cls
    return cls


def build(cfg: TaskGeneratorConfig) -> TaskGenerator:
    cls = _REGISTRY.get(cfg.type)
    if cls is None:
        raise ValueError(
            f"No task generator registered for type {cfg.type!r}. Registered: {sorted(_REGISTRY)}"
        )

View on GitHub (pinned to 24c60942c5)

Solutions

  1. Add a unique non-empty class attribute: TASK_GENERATOR_TYPE = "my_generator".
  2. If the class is abstract/intermediate, don't apply the decorator to it.
  3. Use the same string you reference in TaskGeneratorConfig.type so build() resolves it.

Example fix

# before
@register_task_generator
class MyGen(TaskGenerator):
    ...

# after
@register_task_generator
class MyGen(TaskGenerator):
    TASK_GENERATOR_TYPE = "my_gen"
Defensive patterns

Strategy: validation

Validate before calling

from grox.core.generators.registry import registered_types

assert MyGen.TASK_GENERATOR_TYPE, "set TASK_GENERATOR_TYPE before registering"

Type guard

def has_generator_type(cls) -> bool:
    return bool(getattr(cls, "TASK_GENERATOR_TYPE", None))

Try / catch

try:
    register_task_generator(cls)
except ValueError as e:
    if "TASK_GENERATOR_TYPE" in str(e):
        cls.TASK_GENERATOR_TYPE = derived_default(cls)
        register_task_generator(cls)
    else:
        raise

Prevention

When it happens

Trigger: Registering a TaskGenerator subclass that doesn't define TASK_GENERATOR_TYPE, or defines it as None/empty string/empty value.

Common situations: New generator class written by copying a template without filling in the type constant; subclass meant to be abstract accidentally registered; constant renamed in a refactor.

Related errors


AI-assisted analysis of xai-org/x-algorithm@24c60942c5 (2026-08-28). Data as JSON: /api/errors/71a659a5506de444. Report an issue: GitHub.