Independent project. Not affiliated with or endorsed by Comfy Org.

All pages

Reference

Troubleshooting

What the common startup failures and error codes mean, and what to change. Every API error carries a code; start with the one you got.

View as Markdown Source on GitHub

The proxy will not start

The port is taken. The proxy exits 1 and names the address, where the port value came from, and how to change it. It never moves to another port, because clients are configured with this one. Stop whatever holds the port, or set another with --port, COMFY_PROXY_PORT, or port in the config file.

ss -ltnp 'sport = :8189'        # what holds the port (Linux)
comfy-api-proxy status          # is it a background proxy you started earlier?

"refusing to bind non-loopback host". Exit 2. Binding anything but loopback needs a token, so the API is never open on a network unauthenticated. Set token, or set allow_insecure_bind when the network itself is trusted. See Remote access.

An unknown key or a wrong type in the config file. Exit 2, naming the file and the key. comfy-api-proxy config prints the resolved configuration and the source of every value.

Health says unreachable

GET /api/v2/health reports whether the proxy can reach ComfyUI. Job calls answer 503 upstream_unreachable when ComfyUI is down, and also when it answers with something that is not ComfyUI's JSON (a login page from a gateway, for example). Uploads and downloads answer upstream_error instead.

  • Check the URL: comfy-api-proxy config shows comfyui and where it came from.
  • ComfyUI behind an authenticating gateway: set comfyui_token, which is sent as a bearer token on every call to ComfyUI.
  • The proxy never uses HTTP_PROXY or HTTPS_PROXY for ComfyUI, because those calls can carry a partner API key. A ComfyUI only reachable through an HTTP proxy will not work.

Error codes

Every error is {"error": {"code", "message", "details"}}. The codes you are most likely to see:

Status Code Meaning and fix
401 unauthorized A token is set and the request has no valid Authorization: Bearer header. GET /api/v2/health is the only route without auth.
403 forbidden_origin A browser request from another site. Add the page's origin with --enable-cors-header or cors_origins.
404 not_found No such job or asset. A tampered or truncated output id also reads as not found.
404 output_unavailable The output is listed but its file is gone from ComfyUI's output folder.
413 payload_too_large The upload exceeds max_upload_mb (100 by default).
422 workflow_format_ui The workflow is in the editor's save format. Export it with Export (API).
422 invalid_workflow ComfyUI rejected the graph. details carries ComfyUI's node_errors.
422 missing_asset The workflow references an asset id the proxy does not know.
422 idempotency_key_reuse That Idempotency-Key was already used. A reused key is refused, not replayed, so send a new key with each new job.
422 invalid_request A field failed validation; the message names it.
429 too_many_streams Eight event streams are already open. Close one, or poll instead.
503 upstream_unreachable Job calls: ComfyUI is down or answered with something that is not ComfyUI. See above.
500, 502 upstream_error Uploads and downloads: ComfyUI could not be reached, refused the upload, or answered an output request with an unexpected status.

API reference lists every route's codes.

A browser client is blocked

Browsers send Origin and Sec-Fetch-Site, and the proxy's origin guard refuses cross-site requests unless the origin is allowlisted. Allowlist the exact origin, scheme and port included:

comfy-api-proxy --enable-cors-header http://localhost:5173

CORS headers are added before auth runs, so an allowlisted page can read a 401 instead of seeing an opaque network error.

Large uploads fail

Each upload is written to a temp file while it is hashed, before it goes on to ComfyUI or the model folder. The file goes in the system temp directory, $TMPDIR or /tmp on Linux and macOS, so concurrent uploads need that much free space there. On a machine with a small or RAM-backed /tmp, point TMPDIR at a disk with room before starting the proxy:

TMPDIR=/var/tmp comfy-api-proxy start

An upload larger than max_upload_mb is refused with 413 payload_too_large. The proxy stops reading one byte past the limit, so a never-ending upload cannot fill the disk, and the partial temp file is removed.

A job never finishes

  • Check ComfyUI's own console. A job waiting on a missing model or custom node sits in ComfyUI's queue; the proxy reports what ComfyUI reports.
  • GET /api/v2/jobs/{id} reads ComfyUI's history and queue on every call, so it always shows ComfyUI's current state, even if an event stream missed a message.
  • Cancel with POST /api/v2/jobs/{id}/cancel. The job reads canceling and then canceled.

State is lost after a restart

Without --state-dir, the proxy keeps its own records in memory. A job's status still reads after a restart, because every read asks ComfyUI, and output ids still resolve, because they are signed rather than stored. What a restart loses is what only the proxy knew: each job's submitted workflow and labels, the idempotency keys it has seen, and its index of uploaded assets. Set state_dir to keep them in SQLite; see State and background service.