{"record":{"id":"3489ad87a139c9df","repo":"xai-org/x-algorithm","slug":"all-weights-must-be-positive","errorCode":null,"errorMessage":"All weights must be positive","messagePattern":"All weights must be positive","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"grox/core/generators/task_generator.py","lineNumber":75,"sourceCode":"    def _poll(self) -> AsyncGenerator[TaskPayload | None, None]:\n        pass\n\n    async def ack(self, result: TaskResult):\n        pass\n\n    def identify_task_origin(self, result: TaskResult) -> str | None:\n        return self.TASK_GENERATOR_TYPE\n\n    def on_terminal_failure(self, result: TaskResult) -> None:\n        pass\n\n\nclass PriorityTaskGenerator(TaskGenerator):\n    def __init__(self, generators: list[tuple[TaskGenerator, int]]):\n        if not generators:\n            raise ValueError(\"No generators provided\")\n        if any(weight <= 0 for _, weight in generators):\n            raise ValueError(\"All weights must be positive\")\n        super().__init__(None)\n        self._generators: dict[str, TaskGenerator] = {}\n        self._weights: dict[str, int] = {}\n        for i, (gen, weight) in enumerate(generators):\n            label = f\"GEN_{i}\"\n            self._generators[label] = gen\n            self._weights[label] = weight\n        self._result_cache: dict[str, str] = {}\n        logger.info(\n            f\"Initialized priority task generator with {list(zip(self._generators.keys(), [gen.__class__.__name__ for gen in self._generators.values()], self._weights.values(), strict=True))}\"\n        )\n\n    async def start(self) -> None:\n        logger.info(\"Starting priority task generators\")\n        await asyncio.gather(*[gen.start() for gen in self._generators.values()])\n        self._streams = {label: gen.poll() for label, gen in self._generators.items()}\n        logger.info(\"Priority task generators started\")\n","sourceCodeStart":57,"sourceCodeEnd":93,"githubUrl":"https://github.com/xai-org/x-algorithm/blob/24c60942c5c5fdad3a6addffb4c6e6d2f228f04f/grox/core/generators/task_generator.py#L57-L93","documentation":"PriorityTaskGenerator uses integer weights for weighted round-robin polling, so every weight must be a positive integer (>0). Any zero or negative weight would break the polling arithmetic, so the constructor validates them all up front.","triggerScenarios":"Passing a (generator, weight) tuple with weight 0 (e.g. to 'disable' a generator), a negative number, or a computed weight that evaluates to <=0.","commonSituations":"Config weights parsed as 0 for disabled entries; arithmetic that computes weights and underflows to 0/negative; misunderstanding 0 as 'lowest priority' instead of 'invalid'.","solutions":["Remove zero/negative-weight entries from the list before constructing (to disable a generator, don't include it).","Clamp or default computed weights to at least 1.","Validate config weights at load time with a clear error."],"exampleFix":"# before\npg = PriorityTaskGenerator([(gen_a, 0), (gen_b, 3)])\n\n# after\npg = PriorityTaskGenerator([(gen_b, 3)])  # omit disabled generators","handlingStrategy":"validation","validationCode":"bad = [(g, w) for g, w in generators if w <= 0]\nassert not bad, f\"non-positive weights: {bad}\"\npg = PriorityTaskGenerator(generators)","typeGuard":"def all_weights_positive(generators: list[tuple]) -> bool:\n    return all(w > 0 for _, w in generators)","tryCatchPattern":"try:\n    pg = PriorityTaskGenerator(gens)\nexcept ValueError as e:\n    if \"weights must be positive\" in str(e):\n        gens = [(g, max(w, 1)) for g, w in gens]\n        pg = PriorityTaskGenerator(gens)\n    else:\n        raise","preventionTips":["Use min_weight=1 clamps when computing weights from config.","To disable a generator, omit it rather than giving weight 0.","Validate config weight ranges at load time."],"tags":["python","validation","weights","configuration"],"backgroundTag":"invalid-argument-value","analyzedSha":"24c60942c5c5fdad3a6addffb4c6e6d2f228f04f","analyzedAt":"2026-08-28T11:40:14.686Z","schemaVersion":2},"datasetVersion":"2026-08-28T16:17:29.566Z"}