Switch (model)
Keep three checkpoints wired, pay for one
- models
- model
- selected_index
Flipping between checkpoints mid-project is one of the few things in ComfyUI that's still genuinely annoying. You keep a realistic SDXL and a stylized Flux model wired up, you swap which loader reaches the sampler, and - if you did it naively, with both loaders live on the canvas - you pay to load both. Switch (model) is the node for people who'd rather not. One number decides which of up to ten connected models reaches the sampler, and the loaders you didn't pick never run at all.
The two kinds of switch
"Switch" means two different things in ComfyUI and it's worth knowing which one you want. A first-non-null switch has no selector - it walks its inputs and passes the first one that isn't empty, which is how you build a graph with optional branches that decide themselves (rgthree's Any Switch is the canonical one). An index switch has a number you set - it's a manual routing valve. This is the second kind, and it's a direct descendant of Impact Pack's Switch (Any), which is the node most people have actually used for this job.
The difference from Impact's version is the socket type. Impact takes anything; this one only accepts MODEL, and that's the right call. Type-erasing "connect anything anywhere" nodes are a known way to end up with a graph you can't debug - put the wrong thing on the wire and nothing tells you until something explodes three nodes later. Here, a LATENT into a model socket simply fails at connect time.
How it stays cheap
The node's sockets are declared with ComfyUI's io.Autogrow template: it starts with one empty model_1 slot and grows a new one each time the last is connected, up to model_10. Every one of those sockets is declared lazy=True, and the node implements check_lazy_status to ask the engine for exactly one thing - the socket it has decided to use:
index = _resolve_index(select, models)
value, key = models[f"model_{index}"]
return [key] if value is None else []
Because ComfyUI's execution is pull-based from the output nodes, a loader feeding an unselected socket is simply never asked to produce anything. Its weights are never read off disk. That's the whole point of the node: three Load Diffusion Model nodes on the canvas, one model's worth of loading.
Picking the socket happens in _resolve_index: if select points at a connected socket, use it. If it points at a gap - a middle socket you disconnected - fall back to the highest connected socket below it. If there's nothing below, take the lowest connected one. Setting select past the last model just clamps to the last model. It only raises when nothing at all is connected.
Inputs and outputs
select(INT, default 1, range 1–10) - whichmodel_Nsocket to pass through. 1-based:1picksmodel_1.- the model sockets - the autogrowing group,
MODELonly. A Load Diffusion Model, Load Checkpoint, or a LoRA chain output all connect fine.
Outputs are model and selected_index. The second is quietly the more useful: it tells you which socket actually won after any clamping, so wire it into a Save Image filename prefix (title this node, then use %YourTitle.selected_index% in filename_prefix) and every file records which checkpoint made it - handy when two models are A/B-ing into the same folder.
The select widget's own maximum follows the connected sockets, and connecting, disconnecting or loading a workflow pulls an out-of-range value down onto a socket that's actually connected.
Install
Manager: Custom Nodes Manager → search Y7 → install → restart ComfyUI. Manually:
cd /path/to/ComfyUI/custom_nodes
git clone https://github.com/yushan777/ComfyUI-Y7Nodes
# activate your venv, then:
pip install -r requirements.txt
The pack's requirements.txt is one line, color-matcher>=0.5.0, for the Color Match node - this one needs nothing extra. It does need a current ComfyUI: the pack is written against the newer comfy_api.latest node API and io.Autogrow is a recent core feature. If the pack imports but this node is missing, update ComfyUI before filing anything.
Where people get burned
The subtle one is when the unselected loaders get skipped. They're skipped on runs where they aren't selected - that's it. When you flip select and queue, the newly chosen model has to be loaded, and if the one you were using has been evicted from the VRAM cache you'll pay for that too. So this is a node for flipping between runs and batches, not for alternating models image by image inside one queue.
The other one is the gap fallback. Disconnect model_2 out of three and a select of 2 silently becomes 1 - the log line says so, but nothing on the canvas does. When select is driven by a link instead of the widget, that's worse: the value isn't known until the workflow runs, so the widget can't clamp it and you only find out what happened from selected_index. If a run used the wrong model, that output is where to look.
One version note: this node is new - it landed in the pack's 1.0.60 release, the most recent addition to a pack that keeps changing. If you installed Y7Nodes months ago, hit update in Manager before wondering why the node isn't there.
Inputs (2)
| Name | Type | Default | Description |
|---|---|---|---|
| select | INT | 11–10 | Which model_N socket to pass through. If that one isn't connected, the nearest connected socket below it is used. |
| models | COMFY_AUTOGROW_V3 | Connect one and another empty socket appears, up to ten in total. |
Outputs (2)
| Name | Type | Description |
|---|---|---|
| model | MODEL | — |
| selected_index | INT | The socket number actually used, after clamping. |