{"record":{"id":"2e6d0184008b366e","repo":"Comfy-Org/ComfyUI","slug":"task-cancelled-2e6d01","errorCode":null,"errorMessage":"Task cancelled","messagePattern":"Task cancelled","errorType":"exception","errorClass":"ProcessingInterrupted","httpStatus":null,"severity":"info","filePath":"comfy_api_nodes/util/download_helpers.py","lineNumber":106,"sourceCode":"            async def _monitor():\n                try:\n                    while not stop_evt.is_set():\n                        if is_processing_interrupted():\n                            return\n                        await asyncio.sleep(1.0)\n                except asyncio.CancelledError:\n                    return\n\n            monitor_task = asyncio.create_task(_monitor())\n\n            req_task = asyncio.create_task(session.get(to_aiohttp_url(url), headers=headers))\n            done, pending = await asyncio.wait({req_task, monitor_task}, return_when=asyncio.FIRST_COMPLETED)\n\n            if monitor_task in done and req_task in pending:\n                req_task.cancel()\n                with contextlib.suppress(Exception):\n                    await req_task\n                raise ProcessingInterrupted(\"Task cancelled\")\n\n            try:\n                resp = await req_task\n            except asyncio.CancelledError:\n                raise ProcessingInterrupted(\"Task cancelled\") from None\n\n            async with resp:\n                if resp.status >= 400:\n                    with contextlib.suppress(Exception):\n                        try:\n                            body = await resp.json()\n                        except (ContentTypeError, ValueError):\n                            text = await resp.text()\n                            body = text if len(text) <= 4096 else f\"[text {len(text)} bytes]\"\n                        request_logger.log_request_response(\n                            operation_id=op_id,\n                            request_method=\"GET\",\n                            request_url=url,","sourceCodeStart":88,"sourceCodeEnd":124,"githubUrl":"https://github.com/Comfy-Org/ComfyUI/blob/1c6d8d45b3693bfbb32385b410d813a7fd6be216/comfy_api_nodes/util/download_helpers.py#L88-L124","documentation":"The download helper races the HTTP request against an interrupt monitor task. If the monitor completes first (the user cancelled or interrupted the ComfyUI execution) while the request is still pending, the request is cancelled and ProcessingInterrupted('Task cancelled') is raised. This is intentional cancellation propagation, not a failure.","triggerScenarios":"User hits Cancel/interrupt in the ComfyUI UI (or the queue is cleared) while a GET download in comfy_api_nodes/util/download_helpers.py is still awaiting connection/response headers.","commonSituations":"Cancelling a long-running API-node workflow during its media download phase; queue interruption from another client; frontend-driven execution abort.","solutions":["No fix needed if the cancellation was intentional — this is expected behavior.","If cancellations happen unexpectedly, check whether another session/client is clearing the queue.","Re-run the workflow after the interruption cause is resolved.","Node authors should let ProcessingInterrupted propagate; do not catch-and-continue past it."],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"try:\n    await download(...)\nexcept ProcessingInterrupted:\n    # user cancelled: stop cleanly, keep partial state, do not retry\n    raise","preventionTips":["Never wrap downloads in blanket except-and-retry loops that would defeat cancellation.","Let ProcessingInterrupted propagate to the execution manager.","Educate users that cancelling during download is safe and expected."],"tags":["asyncio","cancellation","processing-interrupted","download"],"backgroundTag":null,"analyzedSha":"1c6d8d45b3693bfbb32385b410d813a7fd6be216","analyzedAt":"2026-08-14T19:37:18.893Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}