{"record":{"id":"7f4bcd463a394cb4","repo":"HKUDS/Vibe-Trading","slug":"cycle-detected-in-task-dag-join-cycle","errorCode":null,"errorMessage":"Cycle detected in task DAG: {' -> '.join(cycle)}","messagePattern":"Cycle detected in task DAG: (.+?)","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"agent/src/swarm/task_store.py","lineNumber":189,"sourceCode":"    path: list[str] = []\n\n    def dfs(node: str) -> None:\n        \"\"\"DFS traversal to detect back edges.\n\n        Args:\n            node: Current node ID.\n\n        Raises:\n            ValueError: If a cycle is detected.\n        \"\"\"\n        color[node] = GRAY\n        path.append(node)\n\n        for neighbor in graph.get(node, []):\n            if color[neighbor] == GRAY:\n                cycle_start = path.index(neighbor)\n                cycle = path[cycle_start:] + [neighbor]\n                raise ValueError(\n                    f\"Cycle detected in task DAG: {' -> '.join(cycle)}\"\n                )\n            if color[neighbor] == WHITE:\n                dfs(neighbor)\n\n        path.pop()\n        color[node] = BLACK\n\n    for tid in all_ids:\n        if color[tid] == WHITE:\n            dfs(tid)\n\n\ndef topological_layers(tasks: list[SwarmTask]) -> list[list[str]]:\n    \"\"\"Kahn's algorithm topological layering; tasks in the same layer can run in parallel.\n\n    Args:\n        tasks: List of SwarmTask (must be a valid acyclic DAG).","sourceCodeStart":171,"sourceCodeEnd":207,"githubUrl":"https://github.com/HKUDS/Vibe-Trading/blob/80ffdda44c5c4db0dd84d70e051cca591cea67df/agent/src/swarm/task_store.py#L171-L207","documentation":"During DFS cycle detection in validate_dag, reaching a GRAY (in-progress) node means the dependency graph has a cycle; the error lists the exact path, e.g. 'a -> b -> c -> a'. Cyclic task graphs can never be scheduled.","triggerScenarios":"Task A depends on B while B depends on A; longer loops introduced by adding a 'final' task that an early task depends on.","commonSituations":"Incrementally adding an aggregation step and wiring it as both consumer and producer; copy-paste editing of depends_on lists.","solutions":["Break the cycle at the edge that points backward (usually the last-added dependency)","Move shared work into a separate upstream task both nodes depend on","Re-run validate_dag after every depends_on edit"],"exampleFix":"# before\nSwarmTask(id='a', depends_on=['b']); SwarmTask(id='b', depends_on=['a'])\n# after\nSwarmTask(id='a', depends_on=[]); SwarmTask(id='b', depends_on=['a'])","handlingStrategy":"validation","validationCode":"validate_dag(tasks)  # run first; reports the exact cycle path","typeGuard":null,"tryCatchPattern":"try:\n    validate_dag(tasks)\nexcept ValueError as e:\n    if 'Cycle detected' in str(e): print(e); break the reported loop\n    else: raise","preventionTips":["Prefer DAGs where edges only point from earlier-defined tasks","Review the last-added depends_on edge when a cycle appears","Add cycle checks to preset CI"],"tags":["python","dag","cycle-detection"],"backgroundTag":"dependency-cycle-detected","analyzedSha":"80ffdda44c5c4db0dd84d70e051cca591cea67df","analyzedAt":"2026-08-28T12:46:38.989Z","schemaVersion":2},"datasetVersion":"2026-08-28T16:17:29.566Z"}