{"record":{"id":"491f5e9a2a3e8609","repo":"xai-org/x-algorithm","slug":"task-generators-not-started","errorCode":null,"errorMessage":"Task generators not started","messagePattern":"Task generators not started","errorType":"exception","errorClass":"RuntimeError","httpStatus":null,"severity":"error","filePath":"grox/core/generators/task_generator.py","lineNumber":102,"sourceCode":"        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\n    async def stop(self) -> None:\n        logger.warning(\"Stopping priority task generators\")\n        await asyncio.gather(*[gen.stop() for gen in self._generators.values()])\n        await super().stop()\n        logger.warning(\"Priority task generators stopped\")\n\n    async def _poll(self) -> AsyncGenerator[TaskPayload | None, None]:\n        if not self._streams:\n            raise RuntimeError(\"Task generators not started\")\n        while self._weights:\n            _weights = self._weights.copy()\n            polled = False\n            while _weights:\n                labels = list(_weights.keys())\n                weights = list(_weights.values())\n                labels = random.choices(labels, weights, k=1)\n                label = labels[0]\n                stream = self._streams[label]\n                try:\n                    payload = await anext(stream)\n                    if payload:\n                        self._result_cache[payload.payload_id] = label\n                        yield payload\n                        polled = True\n                        break\n                    else:\n                        del _weights[label]","sourceCodeStart":84,"sourceCodeEnd":120,"githubUrl":"https://github.com/xai-org/x-algorithm/blob/24c60942c5c5fdad3a6addffb4c6e6d2f228f04f/grox/core/generators/task_generator.py#L84-L120","documentation":"PriorityTaskGenerator._poll reads self._streams, which is only populated during start(). Polling before start() (or after stop() cleared state) means the generator was used out of order, so it raises RuntimeError rather than silently yielding nothing.","triggerScenarios":"Calling the generator's polling/iteration API before awaiting start(); awaiting stop() and then polling again; using the generator after an aborted startup.","commonSituations":"Skipping the start step in tests; race where a consumer task begins polling before the startup task completes; reusing a stopped generator instance.","solutions":["Ensure `await generator.start()` completes before any polling/iteration begins.","Don't reuse a PriorityTaskGenerator after stop(); construct a fresh instance.","In async setups, await start() inside the same task/flow that creates the generator before handing it to consumers.","Add a startup readiness check or event before starting consumers."],"exampleFix":"# before\npg = PriorityTaskGenerator(gens)\nasync for task in pg: ...  # RuntimeError: not started\n\n# after\npg = PriorityTaskGenerator(gens)\nawait pg.start()\nasync for task in pg: ...","handlingStrategy":"validation","validationCode":"await pg.start()\nassert pg._streams, \"start() must populate streams before polling\"","typeGuard":"async def is_started(pg) -> bool:\n    return bool(getattr(pg, \"_streams\", None))","tryCatchPattern":"try:\n    async for task in pg:\n        ...\nexcept RuntimeError as e:\n    if \"not started\" in str(e):\n        await pg.start()\n    else:\n        raise","preventionTips":["Always await start() immediately after construction, before consumer tasks run.","Gate consumers on a readiness event set after start() completes.","Never reuse a stopped generator; create a new instance instead."],"tags":["python","asyncio","lifecycle","runtime-state"],"backgroundTag":"resource-not-initialized","analyzedSha":"24c60942c5c5fdad3a6addffb4c6e6d2f228f04f","analyzedAt":"2026-08-28T11:40:14.686Z","schemaVersion":2},"datasetVersion":"2026-08-28T16:17:29.566Z"}