ComfyUI Node

Any Match Router

Type a word, and the value takes that one of 64 paths

By ArtemKo7v·Created 28 days ago·Updated 3 days ago· 1
Any Match Router
  • any
  • any_out_1
  • any_out_2
  • any_out_3
  • any_out_4
  • any_out_5
  • any_out_6
  • any_out_7
  • any_out_8
  • any_out_9
  • any_out_10
  • any_out_11
  • any_out_12
  • any_out_13
  • any_out_14
  • any_out_15
  • any_out_16
  • any_out_17
  • any_out_18
  • any_out_19
  • any_out_20
  • any_out_21
  • any_out_22
  • any_out_23
  • any_out_24
  • any_out_25
  • any_out_26
  • any_out_27
  • any_out_28
  • any_out_29
  • any_out_30
  • any_out_31
  • any_out_32
  • any_out_33
  • any_out_34
  • any_out_35
  • any_out_36
  • any_out_37
  • any_out_38
  • any_out_39
  • any_out_40
  • any_out_41
  • any_out_42
  • any_out_43
  • any_out_44
  • any_out_45
  • any_out_46
  • any_out_47
  • any_out_48
  • any_out_49
  • any_out_50
  • any_out_51
  • any_out_52
  • any_out_53
  • any_out_54
  • any_out_55
  • any_out_56
  • any_out_57
  • any_out_58
  • any_out_59
  • any_out_60
  • any_out_61
  • any_out_62
  • any_out_63
  • any_out_64
match
text_1
text_2
text_3
text_4
text_5
text_6
text_7
text_8
text_9
text_10
text_11
text_12
text_13
text_14
text_15
text_16
text_17
text_18
text_19
text_20
text_21
text_22
text_23
text_24
text_25
text_26
text_27
text_28
text_29
text_30
text_31
text_32
text_33
text_34
text_35
text_36
text_37
text_38
text_39
text_40
text_41
text_42
text_43
text_44
text_45
text_46
text_47
text_48
text_49
text_50
text_51
text_52
text_53
text_54
text_55
text_56
text_57
text_58
text_59
text_60
text_61
text_62
text_63
text_64

ComfyUI has no switch statement - you get a wired graph, and every branch you build always runs. Any Match Router is the closest thing to switch (x) { case ... } in this pack: one input value, up to 64 outputs, and a match text box that decides which single output receives it. Everything else gets nothing.

How the routing actually works

The implementation is a short loop, and its three quirks are all visible in it:

result = [None] * self.MAX_OUTPUT_INDEX
for index in range(1, self.MAX_OUTPUT_INDEX + 1):
    text = str(kwargs.get(f"text_{index}", ""))
    if text and text == match:
        result[index - 1] = any
        break
return tuple(result)

Read that carefully, because it defines the node:

  • It's plain string equality. Case-sensitive, whitespace-sensitive, whole-string. No substring matching, no regex, no wildcards and no fuzzy anything. Cat does not match cat, and a trailing space you didn't see will make you think the node is broken.
  • An empty text field is skipped, and match is compared as-is. So an empty match matches nothing at all - every output comes back None. That's the single most common way to sit there wondering why nothing is flowing.
  • The first match wins and the loop breaks. Duplicate words across two text fields are a bug, not a shortcut: index 1 gets the value and the later twin gets nothing.

The node's declared inputs are any (required, wildcard - the value being routed) and match (STRING, the word you're testing against), plus the optional text_1text_64 fields that label the destinations. The outputs are any_out_1any_out_64. Backend-side, all 64 outputs are returned every run, mostly as None; the frontend hides the ones you haven't named.

The slots build themselves

This is where the schema and the screen disagree. The 64 text fields and 64 outputs aren't all on screen: a small frontend extension ships with the pack (web/js/dynamic_selectors.js) and maintains them as you type. Fill the last visible text field and the next one appears; an output socket is created only when its text field has something in it.

Two consequences worth internalizing. An output exists because you named it - delete the text in text_5 and any_out_5 vanishes, taking its wire with it, so save before you clear. And the socket labels are purely cosmetic: the visible output type mirrors whatever you plugged into any for readability, but the backend still treats it as wildcard.

If the node shows up with one output and no extra text fields, the extension didn't load - restart ComfyUI and hard-reload the browser tab (Ctrl+Shift+R). If you've turned on Nodes 2.0, know that the Vue frontend has been breaking third-party extensions for months; the standing workaround is to leave it off.

What you'd actually use it for

The killer feature isn't that it routes - a switch does that - it's that the router is driven by data. match is a normal STRING widget, so you can convert it to an input and let an upstream string decide the path: feed it a keyword, a label, a name that falls out of your own pipeline, and the graph reorganizes itself without you touching a wire.

Kept as a widget it's still useful: a variant selector, where you flip a word instead of rewiring. Against its packmates - Any Switch is A/B, Any If Else picks between two values, this one is dispatch.

One caveat, since the plumbing layer has a small culture war about this: routing any type into any socket is what earned the "please stop using the Anything Anywhere extension" backlash. Wildcard wiring makes a graph work and makes it harder to debug. Use it for dispatch you understand.

Installing it

MIT, brand new (first commits September 2026), and zero Python dependencies - empty dependency list, no requirements.txt, nothing to pip. It publishes to the ComfyUI registry automatically, so Manager sees it.

Manager → search ComfyUI Useful Stuff Nodes → Install. Or:

cd ComfyUI/custom_nodes
git clone https://github.com/ArtemKo7v/ComfyUI-UsefulStuffNodes

Restart ComfyUI, then reload the browser page - for this node that's not optional, because the dynamic slots are frontend work.

Where it goes wrong

All outputs None. Either match is empty, nothing matches its exact text, or the case/whitespace differs. The node can't tell you which, because it deliberately does nothing when there's no match. Copy the word straight out of the text field into match to rule out invisible characters.

Downstream nodes erroring. Same mechanism as any switch: the losing outputs carry None, the nodes behind them still execute, and anything expecting a real image or latent complains - usually naming the innocent node, not this one.

Missing node on a borrowed workflow. The JSON stores ArtemKo7vUsefulStuffNodesAnyMatchRouter; expect the red box until you install the pack.

Verdict: this is the one worth installing the pack for. It's a string-keyed dispatcher with no dependencies and no model downloads, and if you run workflows in several variants it removes a class of manual rewiring you'd otherwise be doing at 2am.

CategoryArtemKo7v

Inputs (66)

NameTypeDefaultDescription
any*
matchSTRING
text_1optSTRING
text_2optSTRING
text_3optSTRING
text_4optSTRING
text_5optSTRING
text_6optSTRING
text_7optSTRING
text_8optSTRING
text_9optSTRING
text_10optSTRING
text_11optSTRING
text_12optSTRING
text_13optSTRING
text_14optSTRING
text_15optSTRING
text_16optSTRING
text_17optSTRING
text_18optSTRING
text_19optSTRING
text_20optSTRING
text_21optSTRING
text_22optSTRING
text_23optSTRING
text_24optSTRING
text_25optSTRING
text_26optSTRING
text_27optSTRING
text_28optSTRING
text_29optSTRING
text_30optSTRING
text_31optSTRING
text_32optSTRING
text_33optSTRING
text_34optSTRING
text_35optSTRING
text_36optSTRING
text_37optSTRING
text_38optSTRING
text_39optSTRING
text_40optSTRING
text_41optSTRING
text_42optSTRING
text_43optSTRING
text_44optSTRING
text_45optSTRING
text_46optSTRING
text_47optSTRING
text_48optSTRING
text_49optSTRING
text_50optSTRING
text_51optSTRING
text_52optSTRING
text_53optSTRING
text_54optSTRING
text_55optSTRING
text_56optSTRING
text_57optSTRING
text_58optSTRING
text_59optSTRING
text_60optSTRING
text_61optSTRING
text_62optSTRING
text_63optSTRING
text_64optSTRING

Outputs (64)

NameTypeDescription
any_out_1*
any_out_2*
any_out_3*
any_out_4*
any_out_5*
any_out_6*
any_out_7*
any_out_8*
any_out_9*
any_out_10*
any_out_11*
any_out_12*
any_out_13*
any_out_14*
any_out_15*
any_out_16*
any_out_17*
any_out_18*
any_out_19*
any_out_20*
any_out_21*
any_out_22*
any_out_23*
any_out_24*
any_out_25*
any_out_26*
any_out_27*
any_out_28*
any_out_29*
any_out_30*
any_out_31*
any_out_32*
any_out_33*
any_out_34*
any_out_35*
any_out_36*
any_out_37*
any_out_38*
any_out_39*
any_out_40*
any_out_41*
any_out_42*
any_out_43*
any_out_44*
any_out_45*
any_out_46*
any_out_47*
any_out_48*
any_out_49*
any_out_50*
any_out_51*
any_out_52*
any_out_53*
any_out_54*
any_out_55*
any_out_56*
any_out_57*
any_out_58*
any_out_59*
any_out_60*
any_out_61*
any_out_62*
any_out_63*
any_out_64*