PIL.Image.fromarray accepts 2-channel (LA mode) arrays as well, not
just 1/3/4-channel. Reword the inline comments and test docstrings to
say 'rejects > 4-channel arrays', which is the actual constraint
driving the cap. Also drop a too-narrow 'mode in (L, RGB, RGBA)'
assertion in test_save_compatible_output_passes_through_pil so a
future 2-channel result would not be flagged as a failure.
Address review feedback: the previous fix allowed ImageBlend to return
tensors with > 4 channels (e.g. blending a 3-channel and a 5-channel
image produced a 5-channel tensor). This shifted the original failure
from blend-time to save/preview-time, because SaveImage and PreviewImage
both call PIL.Image.fromarray, which only supports 1/3/4-channel arrays.
Fix:
- In Blend.execute, the alignment target is now min(max(c1, c2), 4):
any image with more than 4 channels is truncated, any image with
fewer is padded with 1.0s up to the (capped) target. This makes the
RGB/RGBA case work and also makes the >4-channel case work end-to-end
rather than just deferring its failure.
- Update the regression test that previously codified the wrong
5-channel-output behavior to assert the correct 4-channel cap.
- Add test_output_capped_at_four_channels (both inputs > 4 channels).
- Add test_save_compatible_output_passes_through_pil that mirrors
SaveImage's exact PIL.Image.fromarray conversion to catch regressions
in the save/preview path.
- Add a small workflow-validation test (image_blend_workflow_test.py)
that loads tests/inference/graphs/image_blend_channel_mismatch.json
and verifies its node types and wiring, so the demo workflow can't
silently bitrot.
Verified end-to-end against a local ComfyUI server: the workflow runs,
output is RGBA, downstream SaveImage succeeds.
Adds a self-contained API workflow at
tests/inference/graphs/image_blend_channel_mismatch.json that exercises
the previously-broken RGB + RGBA blend case end-to-end:
EmptyImage (RGB, red) -> image1
EmptyImage (RGB, blue)
+ SolidMask (0.5) -> JoinImageWithAlpha (RGBA) -> image2
-> ImageBlend (3ch + 4ch)
-> SaveImage
The workflow uses no model checkpoints and runs in seconds on CPU. With
the fix it produces a 4-channel RGBA output (alpha preserved); the
previous behavior would have silently dropped the alpha channel via
node_helpers.image_alpha_fix.
Verified end-to-end against a local ComfyUI instance: workflow executes
successfully, output PNG is RGBA, center pixel is (127, 0, 127, 191) -
red and blue blended at 0.5 with alpha 0.5*1.5=0.75 (191/255).
- test_output_clamped now uses inputs that would produce -0.5 without
clamping, so it actually exercises the torch.clamp(..., 0, 1) call.
- test_padding_value_is_one verifies that the channel-alignment logic
pads with 1.0 specifically (not 0.0 or some other value), which is the
semantic guarantee of treating the extra channel as an opaque alpha.
- Add regression tests covering RGB+RGBA, RGBA+RGB, channel gap > 1
(the exact CORE-103 error case), all blend modes with mismatch, and
output value clamping.
- Soften the inline comment to reflect that channel padding is well-
defined for alpha-like extra channels rather than claiming support
for arbitrary channel layouts.
Replace the limited node_helpers.image_alpha_fix call (which only handles
RGB<->RGBA differences by padding by exactly one channel) with the same
generalized channel-padding logic used by the ImageStitch node.
This allows ImageBlend to work with any combination of channel counts
(e.g. 3 vs 4, 3 vs 5, 4 vs 3, etc.) by padding the image with fewer
channels using 1.0s up to the larger channel count. Behavior between
ImageBlend and ImageStitch is now consistent.
Fixes CORE-103.
* Add OpenAPI 3.1 specification for ComfyUI API
Adds a comprehensive OpenAPI 3.1 spec documenting all HTTP endpoints
exposed by ComfyUI's server, including prompt execution, queue management,
file uploads, userdata, settings, system stats, object info, assets,
and internal routes.
The spec was validated against the source code with adversarial review
from multiple models, and passes Spectral linting with zero errors.
Also removes openapi.yaml from .gitignore so the spec is tracked.
* Mark /api/history endpoints as deprecated
Address Jacob's review feedback on PR #13397 by explicitly marking the
three /api/history operations as deprecated in the OpenAPI spec:
* GET /api/history -> superseded by GET /api/jobs
* POST /api/history -> superseded by /api/jobs management
* GET /api/history/{prompt_id} -> superseded by GET /api/jobs/{job_id}
Each operation gains deprecated: true plus a description that names the
replacement. A formal sunset timeline (RFC 8594 Deprecation and RFC 8553
Sunset headers, minimum-runway policy) is being defined separately and
will be applied as a follow-up.
* Address Spectral lint findings in openapi.yaml
- Add operation descriptions to 52 endpoints (prompt, queue, upload,
view, models, userdata, settings, assets, internal, etc.)
- Add schema descriptions to 22 component schemas
- Add parameter descriptions to 8 path parameters that were missing them
- Remove 6 unused component schemas: TaskOutput, EmbeddingsResponse,
ExtensionsResponse, LogRawResponse, UserInfo, UserDataFullInfo
No wire/shape changes. Reduces Spectral findings from 92 to 4. The
remaining 4 are real issues (WebSocket 101 on /ws, loose error schema,
and two snake_case warnings on real wire field names) and are worth
addressing separately.
* fix(openapi): address jtreminio oneOf review on /api/userdata
Restructure the UserData response schemas to address the review feedback
on the `oneOf` without a discriminator, and fix two accuracy bugs found
while doing it.
Changes
- GET /api/userdata response: extract the inline `oneOf` to a named
schema (`ListUserdataResponse`) and add the missing third variant
returned when `split=true` and `full_info=false` (array of
`[relative_path, ...path_components]`). Previously only two of the
three actual server response shapes were described.
- UserDataResponse (POST endpoints): correct the description — this
schema is a single item, not a list — and point at the canonical
`GetUserDataResponseFullFile` schema instead of the duplicate
`UserDataResponseFull`. Also removes the malformed blank line in
`UserDataResponseShort`.
- Delete the now-unused `UserDataResponseFull` and
`UserDataResponseShort` schemas (replaced by reuse of
`GetUserDataResponseFullFile` and an inline string variant).
- Add an `x-variant-selector` vendor extension to both `oneOf` sites
documenting which query-parameter combination selects which branch,
since a true OpenAPI `discriminator` is not applicable (the variants
are type-disjoint and the selector lives in the request, not the
response body).
This keeps the shapes the server actually emits (no wire-breaking
change) while making the selection rule explicit for SDK generators
and readers.
---------
Co-authored-by: guill <jacob.e.segal@gmail.com>
Currently if the graph contains a cycle, the just inifitiate recursions,
hits a catch all then throws a generic error against the output node
that seeded the validation. Instead, fail the offending cycling mode
chain and handlng it as an error in its own right.
Co-authored-by: guill <jacob.e.segal@gmail.com>
This was doing an over-estimate of VRAM used by the async allocator when lots
of little small tensors were in play.
Also change the versioning scheme to == so we can roll forward aimdo without
worrying about stable regressions downstream in comfyUI core.
* feat(api-nodes): add SD2 real human support
Signed-off-by: bigcat88 <bigcat88@icloud.com>
* fix: add validation before uploading Assets
Signed-off-by: bigcat88 <bigcat88@icloud.com>
* Add asset_id and group_id displaying on the node
Signed-off-by: bigcat88 <bigcat88@icloud.com>
* extend poll_op to use instead of custom async cycle
Signed-off-by: bigcat88 <bigcat88@icloud.com>
* added the polling for the "Active" status after asset creation
Signed-off-by: bigcat88 <bigcat88@icloud.com>
* updated tooltip for group_id
* allow usage of real human in the ByteDance2FirstLastFrame node
* add reference count limits
* corrected price in status when input assets contain video
Signed-off-by: bigcat88 <bigcat88@icloud.com>
---------
Signed-off-by: bigcat88 <bigcat88@icloud.com>
the mixed_precision ops can have input_scale parameters that are used
in tensor math but arent a weight or bias so dont get proper VRAM
management. Treat these as force-castable parameters like the non comfy
weight, random params are buffers already are.
On Windows with aimdo enabled, disable_weight_init.Linear uses lazy
initialization that sets weight and bias to None to avoid unnecessary
memory allocation. This caused a crash when copy_() was called on the
None weight attribute in Stable_Zero123.__init__.
Replace copy_() with direct torch.nn.Parameter assignment, which works
correctly on both Windows (aimdo enabled) and other platforms.
* initial RIFE support
* Also support FILM
* Better RAM usage, reduce FILM VRAM peak
* Add model folder placeholder
* Fix oom fallback frame loss
* Remove torch.compile for now
* Rename model input
* Shorter input type name
---------
The tooltip on the resolution input states that 4K is not available for
veo-3.1-lite or veo-3.0 models, but the execute guard only rejected the
lite combination. Selecting 4K with veo-3.0-generate-001 or
veo-3.0-fast-generate-001 would fall through and hit the upstream API
with an invalid request.
Broaden the guard to match the documented behavior and update the error
message accordingly.
Co-authored-by: Jedrzej Kosinski <kosinkadink1@gmail.com>