Skip to content

Workflow logs a false warning "cancelling N leftover tasks" after every ParallelWorker run in 2.2.0 #6082

@santosflores

Description

@santosflores

🔴 Required Information

Describe the Bug:
Any workflow containing a @node(parallel_worker=True) node fed an N-item
list. Every clean, successful run ends with:

WARNING - _workflow.py:854 - Workflow <name>: cancelling N leftover tasks.

where N equals the worker count, even though all workers completed and their outputs
were delivered downstream.

Completed dynamic runs are never removed from DynamicNodeState.runs, and
run.task is never cleared:

  • _dynamic_node_scheduler.py_record_result() sets status = COMPLETED but does
    not prune the run or clear run.task.
  • _dynamic_node_scheduler.py:101-103get_dynamic_tasks() returns
    [run.task for run in self.runs.values() if run.task] with no task.done() filter.
  • _workflow.py:848-858_cleanup_all_tasks() logs the warning whenever that list is
    non-empty, before checking whether anything actually needs cancelling. The cancel()
    itself is guarded by if not task.done(): and no-ops for finished workers.

Expected Behavior: A clean run should not trigger a warning

Observed Behavior: A false warning being triggered on clean workflow runs

Impact: Cosmetic but misleading. The same warning fires for genuinely stuck tasks,
so on fan-out workflows a real hang becomes indistinguishable from routine noise

Environment Details:

  • ADK Library Version (pip show google-adk):
(.venv) ➜  adk git:(main) ✗ pip show google-adk
Name: google-adk
Version: 2.2.0
Summary: Agent Development Kit
Home-page: https://google.github.io/adk-docs/
Author: 
Author-email: Google LLC <googleapis-packages@google.com>
License: 
Location: /Users/santosflores/Development/agents/adk/.venv/lib/python3.14/site-packages
Requires: aiosqlite, authlib, click, fastapi, google-auth, google-genai, graphviz, httpx, jsonschema, opentelemetry-api, opentelemetry-sdk, packaging, pydantic, python-dotenv, python-multipart, pyyaml, requests, starlette, tenacity, typing-extensions, tzlocal, uvicorn, watchdog, websockets
Required-by: 
  • Desktop OS: macOS
  • Python Version (python -V):
Python 3.14.4

Model Information:

  • Are you using LiteLLM: No
  • Which model is being used: gemini-3.1-flash-lite

🟡 Optional Information

Providing this information greatly speeds up the resolution process.

Regression:
Did this work in a previous version of ADK? If so, which one?

Logs:
Please attach relevant logs. Wrap them in code blocks (```) or attach a
text file.

INFO:     127.0.0.1:62812 - "POST /run_sse HTTP/1.1" 200 OK
2026-06-11 08:47:28,858 - INFO - google_llm.py:208 - Sending out request, model: gemini-3.1-flash-lite, backend: GoogleLLMVariant.VERTEX_AI, stream: False
2026-06-11 08:47:28,859 - INFO - models.py:8635 - AFC is enabled with max remote calls: 10.
2026-06-11 08:47:30,890 - INFO - google_llm.py:277 - Response received from the model.
/Users/santosflores/Development/agents/adk/.venv/lib/python3.14/site-packages/google/adk/tools/mcp_tool/mcp_toolset.py:314: UserWarning: [EXPERIMENTAL] feature FeatureName._MCP_GRACEFUL_ERROR_HANDLING is enabled.
  session = await self._mcp_session_manager.create_session(
2026-06-11 08:47:31,244 - INFO - _client.py:1740 - HTTP Request: POST https://mcp.serpapi.com/9fe5b2435864e377177514a474d1390dbc9dc6ed7ae9d9cfb72e97ffa80eff80/mcp "HTTP/1.1 200 OK"
2026-06-11 08:47:31,247 - INFO - streamable_http.py:193 - Negotiated protocol version: 2025-11-25
2026-06-11 08:47:31,335 - INFO - _client.py:1740 - HTTP Request: POST https://mcp.serpapi.com/9fe5b2435864e377177514a474d1390dbc9dc6ed7ae9d9cfb72e97ffa80eff80/mcp "HTTP/1.1 202 Accepted"
2026-06-11 08:47:31,613 - INFO - _client.py:1740 - HTTP Request: POST https://mcp.serpapi.com/9fe5b2435864e377177514a474d1390dbc9dc6ed7ae9d9cfb72e97ffa80eff80/mcp "HTTP/1.1 200 OK"
/Users/santosflores/Development/agents/adk/.venv/lib/python3.14/site-packages/google/adk/features/_feature_decorator.py:72: UserWarning: [EXPERIMENTAL] feature FeatureName.BASE_AUTHENTICATED_TOOL is enabled.
  check_feature_enabled()
2026-06-11 08:47:31,617 - INFO - _client.py:1740 - HTTP Request: POST https://mcp.serpapi.com/9fe5b2435864e377177514a474d1390dbc9dc6ed7ae9d9cfb72e97ffa80eff80/mcp "HTTP/1.1 200 OK"
2026-06-11 08:47:31,618 - INFO - _client.py:1740 - HTTP Request: POST https://mcp.serpapi.com/9fe5b2435864e377177514a474d1390dbc9dc6ed7ae9d9cfb72e97ffa80eff80/mcp "HTTP/1.1 200 OK"
2026-06-11 08:47:31,857 - INFO - _client.py:1740 - HTTP Request: POST https://mcp.serpapi.com/9fe5b2435864e377177514a474d1390dbc9dc6ed7ae9d9cfb72e97ffa80eff80/mcp "HTTP/1.1 200 OK"
2026-06-11 08:47:31,867 - INFO - _client.py:1740 - HTTP Request: POST https://mcp.serpapi.com/9fe5b2435864e377177514a474d1390dbc9dc6ed7ae9d9cfb72e97ffa80eff80/mcp "HTTP/1.1 200 OK"
2026-06-11 08:47:31,895 - INFO - _client.py:1740 - HTTP Request: POST https://mcp.serpapi.com/9fe5b2435864e377177514a474d1390dbc9dc6ed7ae9d9cfb72e97ffa80eff80/mcp "HTTP/1.1 200 OK"
2026-06-11 08:47:32,140 - INFO - _client.py:1740 - HTTP Request: POST https://mcp.serpapi.com/9fe5b2435864e377177514a474d1390dbc9dc6ed7ae9d9cfb72e97ffa80eff80/mcp "HTTP/1.1 200 OK"
2026-06-11 08:47:32,182 - INFO - _client.py:1740 - HTTP Request: POST https://mcp.serpapi.com/9fe5b2435864e377177514a474d1390dbc9dc6ed7ae9d9cfb72e97ffa80eff80/mcp "HTTP/1.1 200 OK"
2026-06-11 08:47:32,247 - INFO - _client.py:1740 - HTTP Request: POST https://mcp.serpapi.com/9fe5b2435864e377177514a474d1390dbc9dc6ed7ae9d9cfb72e97ffa80eff80/mcp "HTTP/1.1 200 OK"
2026-06-11 08:47:32,484 - INFO - _client.py:1740 - HTTP Request: POST https://mcp.serpapi.com/9fe5b2435864e377177514a474d1390dbc9dc6ed7ae9d9cfb72e97ffa80eff80/mcp "HTTP/1.1 200 OK"
2026-06-11 08:47:32,517 - INFO - _client.py:1740 - HTTP Request: POST https://mcp.serpapi.com/9fe5b2435864e377177514a474d1390dbc9dc6ed7ae9d9cfb72e97ffa80eff80/mcp "HTTP/1.1 200 OK"
2026-06-11 08:47:32,813 - INFO - _client.py:1740 - HTTP Request: POST https://mcp.serpapi.com/9fe5b2435864e377177514a474d1390dbc9dc6ed7ae9d9cfb72e97ffa80eff80/mcp "HTTP/1.1 200 OK"
2026-06-11 08:47:32,824 - INFO - agent.py:96 - len(posts) before deduped: 124
2026-06-11 08:47:32,824 - INFO - agent.py:98 - len(posts) after deduped: 99
2026-06-11 08:47:32,827 - WARNING - _workflow.py:854 - Workflow root_agent: cancelling 3 leftover tasks.

Screenshots / Video:
If applicable, add screenshots or screen recordings to help explain
your problem.

Additional Context:
Add any other context about the problem here.

Minimal Reproduction Code:

import asyncio
import logging

from google.adk import Workflow
from google.adk.runners import InMemoryRunner
from google.adk.workflow import node
from google.genai import types

logging.basicConfig(level=logging.WARNING)


@node
def split(node_input):
    return [1, 2, 3]


@node(parallel_worker=True)
def work(node_input: int) -> int:
    return node_input * 2


@node
def collect(node_input: list):
    return node_input


root_agent = Workflow(
    name="repro",
    edges=[("START", split), (split, work), (work, collect)],
)


async def main():
    runner = InMemoryRunner(agent=root_agent)
    session = await runner.session_service.create_session(
        app_name=runner.app_name, user_id="u"
    )
    async for event in runner.run_async(
        user_id="u",
        session_id=session.id,
        new_message=types.Content(role="user", parts=[types.Part(text="go")]),
    ):
        pass

    # Expected: clean run, workers output [2, 4, 6], no warnings.
    # Actual: WARNING ... Workflow repro: cancelling 3 leftover tasks.


asyncio.run(main())

How often has this issue occurred?:

  • Always (100%)

Metadata

Metadata

Labels

workflow[Component] This issue is related to ADKworkflow

Type

No fields configured for Bug.

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions