From 45fc0bd83af2cf8ac624f72f8ddf167c63b94a63 Mon Sep 17 00:00:00 2001 From: Teknium <127238744+teknium1@users.noreply.github.com> Date: Thu, 16 Apr 2026 06:53:44 -0700 Subject: [PATCH] fix: UnboundLocalError on 'entry' in parallel subagent polling loop (#11050) The completion-line printing block (idx = entry['task_index'] etc.) was outside the 'for future in done:' loop but referenced 'entry' which is only assigned inside that loop. When concurrent.futures.wait() returns with an empty 'done' set (timeout expired, no futures finished), the loop body never executes and 'entry' is unbound. Moved the completion-line printing and spinner-update code inside the for loop so each completed future gets its own status line, and empty poll cycles simply loop back without accessing 'entry'. --- tools/delegate_tool.py | 40 ++++++++++++++++++++-------------------- 1 file changed, 20 insertions(+), 20 deletions(-) diff --git a/tools/delegate_tool.py b/tools/delegate_tool.py index 87218b1b..1b29150f 100644 --- a/tools/delegate_tool.py +++ b/tools/delegate_tool.py @@ -806,28 +806,28 @@ def delegate_task( results.append(entry) completed_count += 1 - # Print per-task completion line above the spinner - idx = entry["task_index"] - label = task_labels[idx] if idx < len(task_labels) else f"Task {idx}" - dur = entry.get("duration_seconds", 0) - status = entry.get("status", "?") - icon = "✓" if status == "completed" else "✗" - remaining = n_tasks - completed_count - completion_line = f"{icon} [{idx+1}/{n_tasks}] {label} ({dur}s)" - if spinner_ref: - try: - spinner_ref.print_above(completion_line) - except Exception: + # Print per-task completion line above the spinner + idx = entry["task_index"] + label = task_labels[idx] if idx < len(task_labels) else f"Task {idx}" + dur = entry.get("duration_seconds", 0) + status = entry.get("status", "?") + icon = "✓" if status == "completed" else "✗" + remaining = n_tasks - completed_count + completion_line = f"{icon} [{idx+1}/{n_tasks}] {label} ({dur}s)" + if spinner_ref: + try: + spinner_ref.print_above(completion_line) + except Exception: + print(f" {completion_line}") + else: print(f" {completion_line}") - else: - print(f" {completion_line}") - # Update spinner text to show remaining count - if spinner_ref and remaining > 0: - try: - spinner_ref.update_text(f"🔀 {remaining} task{'s' if remaining != 1 else ''} remaining") - except Exception as e: - logger.debug("Spinner update_text failed: %s", e) + # Update spinner text to show remaining count + if spinner_ref and remaining > 0: + try: + spinner_ref.update_text(f"🔀 {remaining} task{'s' if remaining != 1 else ''} remaining") + except Exception as e: + logger.debug("Spinner update_text failed: %s", e) # Sort by task_index so results match input order results.sort(key=lambda r: r["task_index"])