Comfy-Org/ComfyUI · error · Exception

Failed to upload (HTTP {resp.status}).

Error message

Failed to upload (HTTP {resp.status}).

What it means

Generic Exception raised when the PUT to upload_url returns an HTTP status >= 400 that is either non-retryable or occurs after retries are exhausted. Retryable statuses {408, 429, 500, 502, 503, 504} are retried up to max_retries with exponential backoff; anything else (or a final failure) raises 'Failed to upload (HTTP {status}).'. The response body/error is logged via request_logger before raising.

Source

Thrown at comfy_api_nodes/util/upload_helpers.py:338

                            request_method="PUT",
                            request_url=upload_url,
                            response_status_code=resp.status,
                            response_headers=dict(resp.headers),
                            response_content=body,
                            error_message=msg,
                        )
                    if resp.status in {408, 429, 500, 502, 503, 504} and attempt <= max_retries:
                        await sleep_with_interrupt(
                            delay,
                            cls,
                            wait_label,
                            start_ts,
                            None,
                            display_callback=_display_time_progress if wait_label else None,
                        )
                        delay *= retry_backoff
                        continue
                    raise Exception(f"Failed to upload (HTTP {resp.status}).")
                request_logger.log_request_response(
                    operation_id=operation_id,
                    request_method="PUT",
                    request_url=upload_url,
                    response_status_code=resp.status,
                    response_headers=dict(resp.headers),
                    response_content="File uploaded successfully.",
                )
                return
        except asyncio.CancelledError:
            raise ProcessingInterrupted("Task cancelled") from None
        except (aiohttp.ClientError, OSError) as e:
            if attempt <= max_retries:
                request_logger.log_request_response(
                    operation_id=operation_id,
                    request_method="PUT",
                    request_url=upload_url,
                    request_headers=headers or None,

View on GitHub (pinned to 1c6d8d45b3)

Solutions

  1. Re-run the node/workflow so a fresh upload_url is minted — expired presigned URLs are the most common cause of 403.
  2. Check request_logger output (operation_id entries) for the exact status and body to identify the provider-side reason.
  3. Match the Content-Type passed to the upload to what the API instructed (do not override mime_type arbitrarily).
  4. For 429/5xx, retry after a longer wait or reduce upload frequency; for oversized files, shrink the payload (e.g., lower total_pixels).
Defensive patterns

Strategy: retry

Try / catch

try:
    url = await upload_image_to_comfyapi(cls, image)
except Exception as e:
    if "Failed to upload (HTTP 403)" in str(e):
        # expired presigned URL: re-run to mint a new one
        url = await upload_image_to_comfyapi(cls, image)

Prevention

When it happens

Trigger: Presigned upload_url returns 403 (expired/signed URL), 410, 400 (bad Content-Type header), or a retryable 5xx that persists past max_retries; resp.status >= 400 and the retry condition (status in {408,429,500,502,503,504} and attempt <= max_retries) is false, so raise Exception at upload_helpers.py:338.

Common situations: Stale presigned URL because the upload request was queued long after the API issued it; wrong Content-Type header vs the signed URL's constraint; provider outage (persistent 502/503); rate limiting (429) exhausting retries; very large uploads exceeding the provider's size limit with a 400.

Related errors


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