ruvnet/ruflo · error
worker dependency cycle: ${remaining.join(', ')}
Error message
worker dependency cycle: ${remaining.join(', ')} What it means
Thrown by the layered scheduler in DualModeOrchestrator when it topologically sorts WorkerConfig entries by dependsOn. Each pass places workers whose dependencies are already placed; if a pass places zero workers while some remain unplaced, the dependency graph can never be satisfied and the error lists the stuck worker ids. Besides true cycles (A depends on B while B depends on A, or a self-dependency), it also fires when dependsOn names an id that is not present in the workers array, because that dependency is never placed.
Source
Thrown at v3/@claude-flow/codex/src/dual-mode/orchestrator.ts:422
const placed = new Set<string>();
while (placed.size < workers.length) {
const level: WorkerConfig[] = [];
for (const worker of workers) {
if (placed.has(worker.id)) continue;
const depsReady = !worker.dependsOn ||
worker.dependsOn.every(dep => placed.has(dep));
if (depsReady) {
level.push(worker);
}
}
if (level.length === 0 && placed.size < workers.length) {
const remaining = workers.filter((worker) => !placed.has(worker.id)).map((worker) => worker.id);
throw new Error(`worker dependency cycle: ${remaining.join(', ')}`);
}
for (const worker of level) {
placed.add(worker.id);
}
if (level.length > 0) {
levels.push(level);
}
}
for (const level of levels) {
const writerPaths = new Set<string>();
const writers = level.filter((item) => !item.readOnly);
for (const worker of writers) {
if (this.config.worktreeIsolation && !worker.worktreePath) {
throw new Error(`writer ${worker.id} requires an isolated worktree`);
}View on GitHub (pinned to fa13ee4ad6)
Solutions
- Read the worker ids in the error message — they are exactly the workers that could never be scheduled; start there
- For each listed worker, trace its dependsOn chain to find the edge that closes the loop (including a self-dependency) and remove or reverse it
- Verify every dependsOn entry matches the id of a worker actually present in the same workers array (watch for typos and stale ids after renames)
- If worker graphs are generated dynamically, run a cycle/unknown-dep check before handing them to the orchestrator
Example fix
// before
const workers = [
{ id: 'build', role: 'coder', dependsOn: ['test'] },
{ id: 'test', role: 'tester', dependsOn: ['build'] }, // build <-> test cycle
];
// after
const workers = [
{ id: 'build', role: 'coder', dependsOn: [] },
{ id: 'test', role: 'tester', dependsOn: ['build'] },
]; Defensive patterns
Strategy: validation
Validate before calling
function assertWorkersSchedulable(workers: WorkerConfig[]): void {
const ids = new Set(workers.map((w) => w.id));
for (const w of workers) {
for (const dep of w.dependsOn ?? []) {
if (!ids.has(dep)) throw new Error(`worker ${w.id} depends on unknown id ${dep}`);
}
}
const placed = new Set<string>();
let progress = true;
while (progress) {
progress = false;
for (const w of workers) {
if (placed.has(w.id)) continue;
if ((w.dependsOn ?? []).every((d) => placed.has(d))) {
placed.add(w.id);
progress = true;
}
}
}
const remaining = workers.filter((w) => !placed.has(w.id)).map((w) => w.id);
if (remaining.length) throw new Error(`dependency cycle among: ${remaining.join(', ')}`);
} Try / catch
Catch Error around the orchestrator run; when the message starts with 'worker dependency cycle', parse the trailing id list and abort the swarm start — retrying without editing the dependsOn graph fails identically every time.
Prevention
- Treat workers as a DAG: single source of truth for ids, with dependsOn values type-checked against it
- Run a cycle check in the config loader or test suite, not at orchestration time
- Never hand-edit dependsOn strings after renaming worker ids — rename programmatically
When it happens
Trigger: Calling the orchestrator run/schedule path with a workers array where (1) two or more workers reference each other in dependsOn, (2) a worker lists its own id in dependsOn, or (3) a dependsOn entry references a typo'd, renamed, or removed worker id that does not exist in the same array.
Common situations: Copy-pasted worker configs where ids were renamed but dependsOn strings were not updated; programmatically generated fan-in/fan-out graphs that accidentally close a loop; merging two swarm configs whose workers each depend on the other's workers.
Related errors
- unattended swarm automation is disabled; set [swarm.automati
- Dual-mode config must export a workers array: ${absolute}
- Invalid --worker spec "${spec}". Expected "<platform>:<role>
- Invalid --worker spec "${spec}". Missing prompt after "<plat
- Invalid platform "${platformRaw}" in --worker spec "${spec}"
AI-assisted analysis of ruvnet/ruflo@fa13ee4ad6 (2026-08-18).
Data as JSON: /api/errors/c552ad6ff8c57579.
Report an issue: GitHub.