Optional String Join (5)
Assemble a real prompt from five optional pieces
- text
Once your prompts get real, they stop being one blob. There's a subject, a quality block, a pose, a scene, lighting, a camera - and half the time you're not sure all of them will be present on any given run. Optional String Join (5), from ruminar's String Join Tools pack, is the node for exactly that situation: five optional string sockets in, one clean prompt out.
The core behavior is identical to the pack's 2- and 3-input joins, just bigger. Every text input is optional and wire-only. Unconnected inputs are ignored. Inputs that resolve to an exact empty string are ignored. The separator appears only between strings that actually exist, so a run where three of your five branches produced nothing still gives you a tidy "subject, scene" instead of ", , , subject, , scene". Whitespace-only strings are kept, embedded line breaks survive, and if everything is missing or empty you get "".
Why five is the practical number
Five sockets maps neatly onto how people actually structure prompts: quality tags, subject, pose or action, environment, lighting. Each is its own upstream branch - a wildcard picker, a LoRA trigger node, a hardcoded text node - and each is allowed to come up empty. Because empty and missing inputs are silently dropped, you can build a composition where any slot is optional and never worry about stray commas leaking into the encoder.
This is also the variant that shines when upstream branches get bypassed. In ComfyUI, bypassing a node can mean its output socket simply isn't there at execution time. This pack was written to accept that - a missing input because a source is bypassed is treated the same as an unconnected socket, which is a nicer failure mode than a hard error or a phantom None.
The bits you'll actually touch
separator- default", ". It decodes\n(newline),\r\n(CRLF),\t(tab), and\\(backslash); anything else is kept as typed.text_1…text_5- optionalSTRINGsockets. Wire them from string sources; they're not type-in fields.- Output:
text, a singleSTRING, good for CLIP Text Encode, a saver's metadata, or feeding another join in a chain.
Everything runs locally, no server round-trips, no state - it's a filter-and-join function in a box, and it's deterministic in a way that makes debugging easy. If the output looks wrong, the answer is in whichever upstream branch produced a string you didn't expect, not in this node.
Installing it
ComfyUI Manager: search "String Join Tools" or "ComfyUI-StringJoinTools" and install. Or manually:
cd ComfyUI/custom_nodes
git clone https://github.com/ruminar/ComfyUI-StringJoinTools
Then restart ComfyUI and refresh the browser. No Python packages, no model downloads - this pack is pure plumbing. Find the node under String Join Tools.
When to reach for the bigger one
Five slots covers most composition needs, but if you're combining a half-dozen optional sources, the (10) variant exists, and the README explicitly blesses chaining joins in stages for unlimited inputs. Start with five; graduate when the graph tells you to.
Inputs (6)
| Name | Type | Default | Description |
|---|---|---|---|
| separator | STRING | , | Inserted only between usable strings. Supports \n, \r\n, \t, and \\. |
| text_1opt | STRING | Optional STRING input. Missing inputs and exact empty strings are ignored. | |
| text_2opt | STRING | Optional STRING input. Missing inputs and exact empty strings are ignored. | |
| text_3opt | STRING | Optional STRING input. Missing inputs and exact empty strings are ignored. | |
| text_4opt | STRING | Optional STRING input. Missing inputs and exact empty strings are ignored. | |
| text_5opt | STRING | Optional STRING input. Missing inputs and exact empty strings are ignored. |
Outputs (1)
| Name | Type | Description |
|---|---|---|
| text | STRING | — |