Apply Character LoRA
The Node That Would Rather Fail Than Render Your Character's Cousin
- model
- char
- clip
- model
- clip
A .char file isn't only a pile of reference images. Characters built in Omnichar Studio or Omnichar Cloud usually carry a trained LoRA inside the same container, and this is the node that puts it on your model.
Why bother, given you can just load a LoRA the normal way
Because a character LoRA is worthless if it lands on the wrong base. The KB's long answer on character consistency says it plainly: training an adapter is still the gold standard for a character you'll reuse, and each model family needs its own, because they don't transfer. In practice people mix up checkpoints constantly - the 9B and 4B Klein LoRAs aren't interchangeable, and neither is anything trained on Krea 2. Load one on the wrong base in a normal LoraLoader and you don't get an error, you get a face that's almost your character. A near miss. Which is worse than a failure, because you spend twenty minutes generating before you notice.
Apply Character LoRA refuses to do that.
How it actually decides
It never pulls the adapter into memory to inspect it. It reads the safetensors header, strips every tensor name down to the module it attaches to, and asks your model which modules it accepts keys for (comfy.lora.model_lora_keys_unet and the CLIP equivalent, with kohya's underscored form added). Then it divides: matched modules over the adapter's total modules. Below your threshold, it raises instead of loading.
If it does load, it goes through ComfyUI's own comfy.sd.load_lora_for_models with the same strength on model and clip, so nothing exotic happens to the weights.
Inputs and outputs
Three required fields. model is your checkpoint, char is the file (wire it from Load Character), and strength defaults to -1, which means "use the strength recorded in the character" - the value it was judged at when the character was trained. Raise it toward 4 if you want more push, but start where the character says.
Of the optional ones, clip matters: wire it and the CLIP comes back patched too. Leave it empty and the clip socket passes straight through. arch names which adapter to use when a character carries several (the SDK raises rather than guessing when there's more than one and you name none). min_key_coverage defaults to 0.9 and is the refusal threshold - leave it alone until you've read the error.
You get two outputs: model into your sampler, and clip into your text encoder path if you fed one in.
Install
ComfyUI Manager, search Omnichar (it's on the registry as "Omnichar Character (.char)"). Or by hand:
cd ComfyUI/custom_nodes
git clone https://github.com/omnichar/ComfyUI-Omnichar
cd ComfyUI-Omnichar
pip install -r requirements.txt
Then restart. No model downloads - the only dependency is omnichar-sdk, pinned to >=0.1,<0.2 on purpose, because a future minor version may change the reader's API. Don't widen that pin casually.
Where people get burned
The refusal error is not a bug, and the message tells you exactly what happened: matches 74 of 131 modules on this model, which is 56%. The fix is to load the base the adapter was trained on - the error quotes that base name from the file - not to drag min_key_coverage down to 0.5 and hope. Lowering it applies a deliberately partial adapter, which is precisely the near-miss case the node exists to prevent.
Two hard limits worth knowing before you file a bug. A character with no adapter at all gets carries no trained adapter, and the answer is to use the reference nodes instead. And some adapters can't be fixed by any slider: their keys use Omnichar Studio's internal naming, which the published checkpoints don't read, so zero modules match. The pack logs a coverage warning when it applies an adapter between your threshold and 100%, which is the one time you want to read the console.
Finally, the boring one that costs people an hour: if omnichar-sdk isn't installed into the environment ComfyUI actually runs in, all eight nodes silently fail to register and your workflow arrives as a wall of missing nodes. The log line starts with "Omnichar character nodes are not loaded". Install into ComfyUI's own venv or portable python_embeded.
Inputs (6)
| Name | Type | Default | Description |
|---|---|---|---|
| model | MODEL | — | |
| char | CHARACTER | — | |
| strength | FLOAT | -1.00-1–4 | How strongly the adapter applies. -1 uses the strength recorded in the character, which is what it was judged at. |
| clipopt | CLIP | — | |
| archopt | STRING | Which adapter, if the character has several. | |
| min_key_coverageopt | FLOAT | 0.900–1 | Refuse the adapter if less than this share of its modules match the model. Lowering it applies a partial adapter on purpose. |
Outputs (2)
| Name | Type | Description |
|---|---|---|
| model | MODEL | — |
| clip | CLIP | — |