Comfy-Org/ComfyUI · error · RuntimeError

Failed to download layer {i + 1} of {len(specs)} (name={item

Error message

Failed to download layer {i + 1} of {len(specs)} (name={item.get('name')!r}): {exc} The generation completed and was billed; the response with all layer URLs is in ComfyUI/temp/api_logs/.

What it means

Raised inside the layer separation node's concurrent download step (semaphore of 4) when download_url_to_image_tensor fails for one of the layer URLs. The message intentionally notes the generation already completed and was billed, and points to ComfyUI/temp/api_logs/ where the full response with all layer URLs is persisted so results are not lost.

Source

Thrown at comfy_api_nodes/nodes_bytedance.py:1322

        else:
            canvas_w, canvas_h = width, height
        base_mask = torch.zeros((1, height, width))
        layers = torch.zeros((len(specs), canvas_h, canvas_w, 3))
        # Create Layered Image / LoadImage mask convention: 1 = transparent
        masks = torch.ones((len(specs), canvas_h, canvas_w))

        semaphore = asyncio.Semaphore(4)

        async def fetch_and_place(i: int, spec: dict) -> None:
            item, flags = spec["item"], spec["flags"]
            left, top, rect_w, rect_h = spec["left"], spec["top"], spec["rect_w"], spec["rect_h"]
            async with semaphore:
                try:
                    rgba = (await download_url_to_image_tensor(str(item["url"])))[0]
                except ProcessingInterrupted:
                    raise
                except Exception as exc:
                    raise RuntimeError(
                        f"Failed to download layer {i + 1} of {len(specs)} (name={item.get('name')!r}): {exc} "
                        "The generation completed and was billed; the response with all layer URLs "
                        "is in ComfyUI/temp/api_logs/."
                    ) from exc
            spec["native_size"] = f"{rgba.shape[1]}x{rgba.shape[0]}"
            if "bbox_degenerate" in flags:
                return
            if (rgba.shape[1], rgba.shape[0]) != (rect_w, rect_h):
                # premultiply before resizing: interpolating straight alpha bleeds the undefined
                # colors of transparent pixels into the anti-aliased edges
                rgba = rgba.clone()
                rgba[..., :3] *= rgba[..., 3:4]
                rgba = (
                    torch.nn.functional.interpolate(
                        rgba.permute(2, 0, 1).unsqueeze(0),
                        size=(rect_h, rect_w),
                        mode="bilinear",
                        antialias=True,

View on GitHub (pinned to 1c6d8d45b3)

Solutions

  1. Recover manually: open the response JSON in ComfyUI/temp/api_logs/ and download the remaining layer URLs directly — you already paid for them.
  2. Simply retry the node if re-billing is acceptable.
  3. Stabilize the network (disable aggressive proxies/VPN) before rerunning expensive layer separations.
Defensive patterns

Strategy: retry

Try / catch

try:
    result = await separate_layers(image)
except RuntimeError as e:
    if 'Failed to download layer' in str(e):
        # generation succeeded and was billed: recover URLs from api_logs
        layers = recover_layer_urls_from_api_logs(task_id)
        result = rebuild_from_urls(layers)  # manual download, avoids re-billing
    else:
        raise

Prevention

When it happens

Trigger: A transient network failure or expired/invalidated layer URL while fetching one of the RGBA layers after a successful generation; ProcessingInterrupted is re-raised untouched, this wrapper covers all other exceptions.

Common situations: Flaky connection or proxy timeout during parallel downloads; layer URLs expiring because the download phase started late; CDN hiccups.

Related errors


AI-assisted analysis of Comfy-Org/ComfyUI@1c6d8d45b3 (2026-08-14). Data as JSON: /api/errors/09f52ca5a269fe98. Report an issue: GitHub.