Outpaint Prompt from Config
The one STRING your editor model wants
- outpaint_config
- outpaint_prompt
What it's for
The outpainting prompt lives in the Outpaint Config bundle. Editors take text nodes. Typed bundles don't connect to STRING sockets. That's the entire problem this node solves, and it solves it in one wire.
outpaint_config in, outpaint_prompt out. No widgets, no state, nothing to configure. It reads the field and returns it.
Where it fits
The intended layout has two consumers off the same config, and this is the text half:
Outpaint Config ──┬─> Outpaint Padding Compute ─ left/top/right/bottom ─> pad / expand canvas
└─> Outpaint Prompt from Config ── STRING ──> editor text encode
The reason to split it this way: the padded canvas and the sentence describing what belongs in it are the same decision. Change the config once and both move together, instead of hunting for a stray text widget three nodes upstream. It also means your prompt travels with the geometry if you copy the config node into a variant workflow.
Pair it with whichever route you're running. On the masked path, the prompt describes the surroundings you want invented at the edges. On the flat-colour path - pad with a solid colour, then ask an instruction model to replace it - the prompt is where the "replace this" instruction lives, and the reader feeds it the same way.
There's no reader for the numbers
Worth flagging, because it's the obvious next question: this reader only exposes the prompt. It tells you nothing about the expansion mode or the resolved margins. If you need the resolved pixel margins as primitives, you don't want a reader - you want Outpaint Padding Compute, which is a real node that takes the same config plus an image and emits left, top, right and bottom as INTs. That's the division of labour: geometry gets computed with the image's dimensions in hand, text gets read out verbatim.
So the two halves of the config have deliberately different consumers. Nothing is wrong if you can't find a "Padding from Config" reader - it doesn't exist, and it isn't needed.
Where people get burned
Wiring outpaint_config into a text node and expecting ComfyUI to figure it out. It won't; the types don't match. Same for PrimitiveString.
One genuinely quiet failure: if the prompt field in the config is empty, this reader happily returns an empty string and your editor gets nothing to work with. Some models will still extend the canvas plausibly with no prompt at all, so you can end up with a subtle "why does it look generic" problem rather than an error. Check the config, not the graph.
And the version trap: 2.0 replaced the 1.x standalone Outpaint Config and unconfigured Padding Compute with this bundle-plus-consumer arrangement. A saved workflow carrying the old nodes won't just be missing a wire - the nodes themselves are gone, and the pack's own guidance is to recreate rather than patch.
Related readers
Same shape, same purpose:
- Crop Prompt from Config -
subject_maskas aSTRING. - Edit Prompt from Config - the inpaint prompt or one of three stitch prompts.
- Seed from Config - the run seed as an
INT. - Scale from Config -
initial_upscaleorfinal_upscaleas aFLOAT. - Save Info from Source - filename and output directory from the loader.
Install
ComfyUI Manager → search PortraitUtils (publisher heyburns, GPLv3), or manually:
cd ComfyUI/custom_nodes
git clone https://github.com/heyburns/PortraitUtils
/path/to/ComfyUI/venv/bin/python -m pip install -r PortraitUtils/requirements.txt
Use ComfyUI's Python environment - numpy, Pillow, opencv-python-headless and tifffile, with only one OpenCV variant present - then restart the ComfyUI server. A browser refresh alone won't register new node classes, which is the usual reason a freshly installed node "doesn't exist."
Inputs (1)
| Name | Type | Default | Description |
|---|---|---|---|
| outpaint_config | PORTRAIT_OUTPAINT_CONFIG_V2 | — |
Outputs (1)
| Name | Type | Description |
|---|---|---|
| outpaint_prompt | STRING | — |