ComfyUI LoRA Not Working: Key Not Loaded Fixes
Want to go deeper than this article?
Free account unlocks the first chapter of all 25 courses — RAG, agents, MCP, voice AI, MLOps, real GitHub repos.
Generating images locally? Take it further. From FLUX and ComfyUI setup to building real image pipelines and apps. First chapter free, no card.
If your LoRA generates fine but changes nothing, scroll your console for the line lora key not loaded: followed by a tensor name. That message means the file loaded perfectly — ComfyUI simply could not match a single one of its tensor names to a layer in your model, so it applied nothing and carried on without raising an error. It is a naming mismatch between the trainer that wrote the file and the architecture you loaded it onto, and the fix is to convert the file to a namespace ComfyUI's key map recognises, not to raise the strength slider. If the console is clean and the output is still identical, check the strength values first: ComfyUI's LoraLoader returns the untouched model when both strengths are zero, and prints nothing at all.
The reason this failure eats so many hours is that every visible signal says success. The node turns green, the sampler runs, the image appears, the workflow completes. The only evidence lives in the terminal, and if you launched ComfyUI by double-clicking something, you may not have a terminal open at all.
Everything below is read from ComfyUI's own source on master — comfy/lora.py, comfy/lora_convert.py, comfy/weight_adapter/ and nodes.py — and from the tensor names inside real LoRA files, inspected with the script in the "read your own file" section. Bug reports are linked to their issue numbers so you can check whether yours has been fixed since.
What Does "lora key not loaded" Actually Mean?
It is one specific logging.warning in comfy/lora.py, emitted once per unmatched tensor, at the very end of load_lora():
if log_missing:
for x in lora.keys():
if x not in loaded_keys:
logging.warning("lora key not loaded: {}".format(x))
Read what loaded_keys is. Before this loop, ComfyUI builds a key_map — a dictionary from every LoRA key name it knows how to interpret to the actual weight in your loaded model — then walks that map looking for matching tensors in your file. Anything in your file that was never looked up ends up here.
So the message is not "this tensor is broken" or "this file is corrupt". It is closer to: "I did not have this name in my dictionary." A LoRA where every key prints this line contributed exactly zero to the generation, which is why the output is pixel-identical to a run with the node bypassed.
Three consequences follow, and they explain most of the confusion around this error:
- It is a warning, not an error. Nothing aborts. The queue completes. If you are not watching the console you get no signal at all.
- Partial loading is possible and is worse than total failure. If half your keys match, you get half a LoRA — a weak, wrong-looking effect that feels like a training problem. Count the warnings against the tensor count of the file.
- The file is fine. The same LoRA very often works in the trainer's own inference script or in a different UI. Issue #12638 is explicit about this: the reporter's ACE-Step LoKr produced a console full of
lora key not loadedin ComfyUI while "the same LoKr works with ACE-Step's Gradio UI."
Reading articles is good. Building is better.
Free account = 20+ free chapters across 25 courses, with a per-chapter AI tutor. No card. Cancel anytime if you ever upgrade.
Which Console Message Do You Actually Have?
Four different messages get reported as "my LoRA is not working" and they have four different causes. Match yours before doing anything.
| What the console shows | Source | What it means | Where to go |
|---|---|---|---|
lora key not loaded: <name> | comfy/lora.py, load_lora() | The key name is not in ComfyUI's dictionary for this architecture | Key-namespace table below |
NOT LOADED <name> | comfy/sd.py, load_lora_for_models() | The key was matched, but neither the model nor the CLIP patcher accepted the patch | Usually a wrong-model mismatch |
WARNING SHAPE MISMATCH <key> WEIGHT NOT MERGED <a> != <b> | comfy/lora.py | Name matched, tensor dimensions did not. That layer is skipped | Wrong architecture entirely |
| Nothing at all, output unchanged | — | No warning was ever generated | Strength is zero, or the node is bypassed |
That second one is worth knowing about because it looks almost the same and is not. In comfy/sd.py:
k = set(k)
k1 = set(k1)
for x in loaded:
if (x not in k) and (x not in k1):
logging.warning("NOT LOADED {}".format(x))
k and k1 are the keys the model patcher and the CLIP patcher actually accepted. NOT LOADED therefore means ComfyUI understood your key name but had nowhere to put it — a different and rarer failure than not recognising the name at all.
The Silent Case: Nothing in the Console
Before you go near key names, rule out the case that produces no output whatsoever. From nodes.py, the very first thing LoraLoader.load_lora does:
def load_lora(self, model, clip, lora_name, strength_model, strength_clip):
if strength_model == 0 and strength_clip == 0:
return (model, clip)
Both strengths at zero and the node hands back your model untouched, never opens the file, and logs nothing. A workflow downloaded from someone else, or a slider nudged during a UI drag, produces a perfectly silent no-op. Set strength_model to something obvious like 1.5 and re-run: if the image is still byte-identical, you have a real loading problem and the rest of this page applies.
Two more silent no-ops worth eliminating in the same minute:
- The node is bypassed or muted. Ctrl+B on a node in ComfyUI passes its input straight through. A bypassed LoraLoader is invisible in a screenshot and identical in behaviour to no node at all.
- The MODEL output is not actually wired to your KSampler. Adding a LoraLoader and forgetting to re-route the KSampler's
modelinput to it is easy in a dense graph, and everything still runs, because the KSampler is happily using the original checkpoint output.
Once you have a non-zero strength and a real wire, any remaining failure will say so in the console.
The Key-Namespace Table
This is the reference the rest of the page hangs on. Every row was produced by reading the tensor names out of a real published LoRA file — the safetensors header, not documentation — using the script in the next section. The "consumed by" column names the branch in model_lora_keys_unet() / model_lora_keys_clip() (in comfy/lora.py) that puts that namespace into the key map.
| Trainer / format | Target arch | Key namespace it writes | Tensors | Consumed by |
|---|---|---|---|---|
kohya-ss sd-scripts (networks.lora) | SDXL | lora_unet_input_blocks_4_1_proj_in.lora_down.weight | 2166 | lora_unet_ branch (native-key path) |
| kohya-ss, diffusers block naming | SDXL | lora_unet_down_blocks_0_resnets_0_conv1.lora_down.weight | 2364 | lora_unet_ branch (via unet_to_diffusers) |
| diffusers / PEFT | FLUX | transformer.single_transformer_blocks.0.attn.to_k.lora_A.weight | 988 | Flux branch, transformer. prefix |
| diffusers / PEFT | FLUX | transformer.context_embedder.lora_A.weight | 1008 | same as above |
| XLabs | FLUX | double_blocks.0.processor.qkv_lora1.down.weight | 152 | nothing — see the XLabs section |
| LyCORIS LoKr via SimpleTuner | FLUX | lycoris_single_transformer_blocks_0_attn_to_k.lokr_w1 | 1026 | Flux branch, lycoris_ prefix |
| LyCORIS LoKr via SimpleTuner | Qwen-Image | lycoris_transformer_blocks_0_attn_add_k_proj.lokr_w1 | 2160 | QwenImage branch, lycoris_ prefix |
| kohya-style, bare keys | Qwen-Image | transformer_blocks.0.attn.add_k_proj.lora_down.weight | 2160 | QwenImage branch, unprefixed path |
ComfyUI-native (diff + LoRA mix) | Wan 2.1 | diffusion_model.blocks.0.cross_attn.k.lora_down.weight, plus .diff / .diff_b | 1459 | generic diffusion_model. branch |
| diffusers PEFT LoKr | SD 1.5 | base_model.model.down_blocks.0...lokr_w1 | — | nothing on SD 1.5 — see issue #9753 |
| Unknown / Z-Image reports | Z-Image | diffusion_model.layers.0.attention.to_k.lora_A.weight | — | reported failing in issue #11158 |
Files inspected for the first nine rows: nerijs/pixel-art-xl, ByteDance/Hyper-SD (Hyper-SDXL-8steps-lora and Hyper-FLUX.1-dev-8steps-lora), multimodalart/flux-tarot-v1, XLabs-AI/flux-RealismLora, terminusresearch/flux-lokr-garfield-nomask, mikaelh/qwen_image.lycoris-lokr.minecraft, lightx2v/Qwen-Image-Lightning, and Kijai/WanVideo_comfy. The last two rows come from the linked issue reports rather than from a file inspection, and are marked as such.
The pattern to take away: the same LoKr training method writes lycoris_single_transformer_blocks_... for FLUX and lycoris_transformer_blocks_... for Qwen-Image, because the prefix is generated from the target model's own layer names. A LoRA is not portable across architectures even when the trainer and adapter type are identical. That is why "this LoKr works for FLUX but not for my new model" is such a common report — and why PR #11997 ("Add LyCORIS LoKr support for Flux2") had to be written as a separate change even though LoKr already worked elsewhere.
Reading articles is good. Building is better.
Free account = 20+ free chapters across 25 courses, with a per-chapter AI tutor. No card. Cancel anytime if you ever upgrade.
What Suffix Is ComfyUI Looking For?
The prefix decides which layer; the suffix decides which adapter maths. ComfyUI's adapters each probe for their own tensor names, and a file using a suffix no adapter recognises is unloadable no matter how correct the prefix is. Read from comfy/weight_adapter/ and comfy/lora.py on master:
| Adapter type | Suffixes probed | File |
|---|---|---|
| LoRA, kohya | .lora_up.weight, .lora_down.weight, .lora_mid.weight | weight_adapter/lora.py |
| LoRA, diffusers/PEFT | .lora_B.weight, .lora_A.weight | same |
| LoRA, diffusers variants | _lora.up.weight / _lora.down.weight, .lora.up.weight / .lora.down.weight | same |
| LoRA, Mochi | .lora_B, .lora_A (no .weight) | same |
| LoRA, transformers | .lora_linear_layer.up.weight | same |
| LoRA, Qwen PEFT default adapter | .lora_B.default.weight | same |
| LoHa | .hada_w1_a, .hada_w1_b, .hada_w2_a, .hada_w2_b, .hada_t1, .hada_t2 | weight_adapter/loha.py |
| LoKr | .lokr_w1, .lokr_w2, .lokr_w1_a, .lokr_w1_b, .lokr_w2_a, .lokr_w2_b, .lokr_t2 | weight_adapter/lokr.py |
| GLoRA | .a1.weight, .a2.weight, .b1.weight, .b2.weight | weight_adapter/glora.py |
| OFT | .oft_blocks, .rescale | weight_adapter/oft.py |
| DoRA | .dora_scale (layered on top of any LoRA form) | comfy/lora.py |
| Direct weight edits | .diff, .diff_b, .set_weight, .w_norm, .b_norm | comfy/lora.py |
| Scaling | .alpha | comfy/lora.py |
Two practical notes. First, .alpha is claimed only when its parent key was matched, which is why unmatched blocks print an .alpha warning alongside the weight warnings — you will see roughly three lines per layer for a kohya LoRA, not one. Second, the Wan file in the table above mixes .lora_down.weight with .diff and .diff_b in a single file: 406 LoRA pairs plus 447 bias diffs plus 200 direct diffs. Both mechanisms are legitimate and both are in that suffix list, which is why a file can be partially LoRA and partially a straight weight replacement.
How to Read Your Own LoRA's Keys
Stop guessing which format you have. A safetensors file stores its full tensor index as a JSON header at the front of the file, so you can read every key name without loading the weights, without a GPU, and without installing anything — this uses only the Python standard library.
import json, re, struct, sys
from collections import Counter
SUFFIXES = [
".lora_up.weight", ".lora_down.weight", ".lora_mid.weight",
".lora_B.weight", ".lora_A.weight", ".lora.up.weight", ".lora.down.weight",
"_lora.up.weight", "_lora.down.weight", ".lora_linear_layer.up.weight",
".lora_B.default.weight", ".lora_A.default.weight",
".hada_w1_a", ".hada_w1_b", ".hada_w2_a", ".hada_w2_b",
".lokr_w1", ".lokr_w2", ".lokr_w1_a", ".lokr_w1_b", ".lokr_w2_a", ".lokr_w2_b",
".oft_blocks", ".a1.weight", ".b1.weight",
".alpha", ".dora_scale", ".diff", ".diff_b", ".set_weight",
]
PREFIXES = re.compile(
r"^(lora_unet_|lora_te\d?_|lora_transformer_|lora_prior_unet_|lycoris_|"
r"transformer\.|diffusion_model\.|text_encoders?\.|base_model\.model\.|unet\.)"
)
path = sys.argv[1]
with open(path, "rb") as f:
header = json.loads(f.read(struct.unpack("<Q", f.read(8))[0]))
keys = [k for k in header if k != "__metadata__"]
print(f"{len(keys)} tensors\n")
for k in sorted(keys)[:8]:
print(" ", k)
print("\nnamespace:")
for p, c in Counter(
(m.group(1) if (m := PREFIXES.match(k)) else "(unprefixed) " + k.split(".")[0])
for k in keys
).most_common(6):
print(f" {p} x{c}")
print("\nadapter suffix:")
def suffix(k):
for s in sorted(SUFFIXES, key=len, reverse=True):
if k.endswith(s):
return s
return "?? " + k
for s, c in Counter(suffix(k) for k in keys).most_common(8):
print(f" {s} x{c}")
for tag in ("ss_network_module", "ss_network_args", "modelspec.architecture"):
if tag in header.get("__metadata__", {}):
print(f"\n{tag}: {header['__metadata__'][tag]}")
Run it against the file that is failing:
python lora_keys.py ComfyUI/models/loras/my_lora.safetensors
Output for a kohya SDXL LoRA looks like this:
2166 tensors
lora_unet_input_blocks_4_1_proj_in.alpha
lora_unet_input_blocks_4_1_proj_in.lora_down.weight
namespace:
lora_unet_ x2166
adapter suffix:
.alpha x722
.lora_down.weight x722
.lora_up.weight x722
ss_network_module: networks.lora
How to read the result. A single clean namespace that appears in the table above, plus suffixes that all resolve, means the file is in a shape ComfyUI understands and the problem is architecture matching. A namespace printed as (unprefixed) something or suffixes printed with ?? means ComfyUI has no dictionary entry for that layout at all — you need a conversion, not a settings change. The ss_network_module line, when kohya wrote it, tells you which trainer produced the file, which is the fastest route to finding the right conversion script.
Bonus: comparing the tensor count printed here against the number of lora key not loaded lines in your console tells you immediately whether you have a total failure or a partial one.
When ComfyUI Simply Does Not Support Your Format
Some formats are not supported and are not going to be, and knowing that saves you a week. The clearest statement of this is on issue #12452, "SDXL Lora keys not loaded (Simpletuner trained)". The reporter had a diffusers-format SDXL LoRA producing keys like:
lora key not loaded: unet.down_blocks.1.attentions.0.transformer_blocks.0.attn1.to_k.lora.down.weight
lora key not loaded: unet.down_blocks.1.attentions.0.transformer_blocks.0.attn1.to_k.lora.up.weight
lora key not loaded: unet.down_blocks.1.attentions.0.transformer_blocks.0.attn1.to_out.0.lora.down.weight
They confirmed it with --disable-all-custom-nodes, which is the right diagnostic. The maintainer's reply closed it:
This model is over 2 years old, at this point I'm not adding support for new lora formats.
Note the suffix in those keys: .lora.down.weight is in ComfyUI's probe list. The prefix is what fails — a diffusers unet. path that does not line up with the entries the key map builds. The lesson generalises: a supported adapter type plus an unsupported prefix is still a total failure, and "but LoKr works for other people" is not evidence that your file will load.
The same shape appears in issue #9753, "Load PEFT lora/lycoris models" (open at the time of writing), where a diffusers-trained SD 1.5 LoKr yields base_model.model.conv_in.lokr_w1 and similar. A commenter there notes the practical workaround the ecosystem settled on: "some trainers such as Side-Step are forced to automatically convert trained LoKRs to ComfyUI format". If your trainer offers a "ComfyUI format" or "convert for Comfy" export option, use it — that option exists precisely because of this.
The XLabs FLUX Case: A Conversion That Does Not Trigger
ComfyUI does convert a few known third-party layouts on load, but the detection is keyed on specific probe tensors, and a file missing them is passed through untouched. From comfy/lora_convert.py:
def convert_lora(sd):
if "img_in.lora_A.weight" in sd and "single_blocks.0.norm.key_norm.scale" in sd:
return convert_lora_bfl_control(sd)
if "lora_unet__blocks_0_cross_attn_k.lora_down.weight" in sd:
return convert_lora_wan_fun(sd)
if "single_blocks.37.processor.qkv_lora.up.weight" in sd and "double_blocks.18.processor.qkv_lora2.up.weight" in sd:
return convert_uso_lora(sd)
return sd
That last branch is the one that handles .processor.*_lora naming — and it requires both a single_blocks.37 probe key and a double_blocks.18 probe key to be present. The XLabs FLUX LoRA inspected for the table (XLabs-AI/flux-RealismLora) contains 152 tensors, all of them under double_blocks., with no single_blocks keys at all. The conversion therefore does not fire for that file, its keys reach load_lora() in their original double_blocks.0.processor.qkv_lora1.down.weight form, and nothing in the key map matches them.
Practically: XLabs-layout FLUX LoRAs are the canonical "needs the trainer's own loader node" case. If the inspection script shows .processor. in the middle of your key names, stop looking for a core-node setting. Either find a converted re-upload of the same LoRA in transformer./lora_A/lora_B form, or install the loader node that ships with that ecosystem. Our ComfyUI FLUX workflow guide covers the graph on the working side of this, and the FLUX.2 setup guide covers the current generation's file layout.
The convert_lora_wan_fun branch above is a nice miniature of the whole problem, incidentally: the entire fix is state_dict_prefix_replace(sd, {"lora_unet__": "lora_unet_"}) — a single stray underscore, written by one trainer, that made an otherwise perfect file invisible.
Text-Encoder Warnings That Are Harmless
A wall of lora key not loaded: lora_te1_... lines does not always mean anything is wrong. This one catches people who did everything right.
LoraLoaderModelOnly in nodes.py calls the shared loader with no CLIP at all:
def load_lora_model_only(self, model, lora_name, strength_model):
return (self.load_lora(model, None, lora_name, strength_model, 0)[0],)
And in comfy/sd.py, the CLIP half of the key map is built only when a CLIP is present:
if clip is not None:
key_map = comfy.lora.model_lora_keys_clip(clip.cond_stage_model, key_map)
So if you use the model-only loader on a LoRA that also trained the text encoder, every lora_te_ / lora_te1_ / lora_te2_ key in the file will print a warning, by design. The UNet half applied correctly. If your LoRA is visibly working but the console is noisy, this is very likely why, and switching to the full LoraLoader with both a MODEL and a CLIP input silences it and applies the text-encoder half as well.
Text-encoder keys are also where genuinely new architectures break first, because the encoder changes more often than the diffusion backbone. Issue #13747 is the clean example: an Anima LoRA whose UNet loaded fine while every lora_te_layers_0_mlp_down_proj-style key failed, because the model uses a Qwen3-0.6B text encoder whose kohya key layout ComfyUI had no mapping for. It was fixed by PR #13847, "Support anima TE lora kohya format," merged 12 May 2026 — so on that one, updating ComfyUI is the fix. It is worth checking whether your specific failure has been patched before you go hunting for a converter.
Shape Mismatch Is a Different, Worse Failure
If your warnings say shape rather than not loaded, you have loaded a LoRA for the wrong architecture, and it can cost you more than a wasted generation. The message comes from comfy/lora.py:
if diff.shape != weight.shape:
logging.warning("WARNING SHAPE MISMATCH {} WEIGHT NOT MERGED {} != {}".format(key, diff.shape, weight.shape))
The name matched; the tensor did not fit; that layer is skipped and execution continues.
Issue #11863 — "LoRA shape mismatches should fail fast instead of corrupting GPU state and causing OOM/system instability", open at the time of writing — is the argument for why continuing is a bad default. The reporter applied a FLUX 1 LoRA to a FLUX 2 Dev model and describes the result as roughly 1500 lora key not loaded warnings followed by roughly 228 shape errors of the form:
ERROR lora diffusion_model.single_blocks.X.linear2.weight shape '[6144, 24576]' is invalid for input of size 47185920
after which, in their words, "Execution continues despite ~1700 logged problems," ending in an out-of-memory failure on a 96GB card. Treat this as a hard stop rather than a warning: if you see shape errors, cancel the run and fix the pairing before queueing anything else. The safe reading is that a LoRA trained for one generation of a model family is not usable on the next one, even when the file loads and the names line up.
Architecture-Specific Reports Worth Checking
Newer model families are where this failure concentrates, because support lands architecture by architecture rather than once. Before assuming your file is bad, check whether your architecture has an open report:
| Architecture | Report | State when written |
|---|---|---|
| Z-Image | #11158 — LoRAs load partially or not at all, keys like diffusion_model.layers.0.attention.to_k.lora_A.weight | Open |
| FLUX 2 Klein, LyCORIS LoKr | #12084 — SimpleTuner LoKr not loading | Closed; support added in PR #11997 |
| ACE-Step 1.5, LoKr | #12638 — lycoris_*.lokr_w2_a keys unmatched | Closed, but a commenter notes results can still be wrong pending PEFT support (#9753) |
| Anima, text encoder | #13747 — lora_te_layers_* unmatched | Closed by PR #13847 |
| Qwen-Image-Edit + PhysicsEdit | #12708 — pipe.dino_resampler.* keys unmatched | Open |
| SDXL, SimpleTuner diffusers | #12452 — unet.*.lora.down.weight unmatched | Closed as not planned |
| Wan 2.1, LyCORIS | #8285 — Wan2.1 14B LyCORIS keys not loaded | Open |
Issue #12708 is a useful one to understand because the answer is not "ComfyUI is broken": the unmatched keys are pipe.dino_resampler.*, an entire auxiliary module that is not part of the diffusion model at all. Some published "LoRAs" bundle extra components that no core loader was ever going to apply. Working with that family? Our Qwen-Image-Edit local guide covers the supported graph, and the Z-Image Turbo ComfyUI guide covers the loader wiring for that one.
Fix Order
Work down this list; each step either fixes it or eliminates a cause.
- Open a console. If you cannot see ComfyUI's log output you cannot debug this. Launch from a terminal.
- Set strength to 1.5 and re-run. Rules out the silent zero-strength no-op and confirms the node is wired in.
- Read the first warning line.
lora key not loaded→ keep going.SHAPE MISMATCH→ stop, wrong architecture. Silence → step 2 again, check for a bypassed node. - Run the inspection script on the failing file and identify the namespace and suffix.
- Compare against the table above. Recognised namespace on the wrong architecture is a pairing problem; unrecognised namespace is a conversion problem.
- Update ComfyUI. Several of the issues in the table were fixed by a merged PR. This is the cheapest possible fix and it is genuinely sometimes the answer.
- Test with
--disable-all-custom-nodes. A custom loader pack can shadow the core node. Every well-triaged report in the tracker includes this step. - Look for a converted re-upload, or re-export from your trainer in ComfyUI format.
- Only then suspect the training. If keys load and the effect is weak, that is a training or strength question, not a loading one — our LoRA training guide and the AI-Toolkit LoRA training guide cover the parameters that actually control effect strength.
FAQ
Why does my LoRA generate an image but change nothing?
Because ComfyUI could not match its tensor names to your model and applied nothing, while still completing the run normally. Look for lora key not loaded: in the console. If the console is silent, the strengths are probably both zero — LoraLoader returns the model untouched in that case without opening the file.
Is "lora key not loaded" an error I should worry about?
It depends on how many you get. A handful of lora_te* lines when you used LoraLoaderModelOnly is expected and harmless — that loader never builds a CLIP key map. A count that matches the file's total tensor count means nothing loaded at all. Run the inspection script above to get the file's tensor count and compare.
Can I fix it by raising the LoRA strength?
No. Strength multiplies patches that were successfully applied. If no keys matched, you are multiplying nothing, and the output stays identical at any strength. Raising strength is a useful diagnostic — an obvious value like 1.5 proves the node is live — but it is not a fix.
Why does my LoKr work in the trainer's UI but not in ComfyUI?
Because they read different key namespaces. Issue #12638 documents exactly this for ACE-Step: the same LoKr worked in ACE-Step's own Gradio UI and produced lora key not loaded in ComfyUI. Several trainers now ship a "convert to ComfyUI format" export for this reason; use it if yours has one.
What is the difference between "lora key not loaded" and "SHAPE MISMATCH"?
The first means ComfyUI did not recognise the key name. The second means it recognised the name but the tensor dimensions did not fit the target layer, so the merge was skipped. The second is more serious — issue #11863 documents a FLUX 1 LoRA on a FLUX 2 model producing hundreds of shape errors and then an out-of-memory failure. Cancel the run rather than letting it continue.
Will updating ComfyUI fix it?
Sometimes, and it is the cheapest thing to try. Support for new LoRA layouts lands as individual PRs — PR #13847 added Anima text-encoder kohya keys, PR #11997 added LyCORIS LoKr for FLUX 2. But formats can also be declined: issue #12452 was closed with "at this point I'm not adding support for new lora formats." Check whether your specific report is open before you wait for a fix.
Do I need custom nodes to load LoRAs?
Not for the mainstream formats — kohya, diffusers/PEFT and LyCORIS all load in the core LoraLoader for supported architectures. You need an ecosystem-specific loader when the file uses a layout ComfyUI's key map does not contain, XLabs-style FLUX LoRAs with .processor. in the key names being the standard example. Test with --disable-all-custom-nodes first, because a custom pack can also be the thing causing the problem.
Sources
- ComfyUI source on
master: comfy/lora.py (thelora key not loadedwarning,model_lora_keys_unet,model_lora_keys_clip, the shape-mismatch warning), comfy/lora_convert.py (the conversion probes),comfy/weight_adapter/(adapter suffixes),comfy/sd.py(NOT LOADED),nodes.py(LoraLoader,LoraLoaderModelOnly) - Comfy-Org/ComfyUI issues #8285, #9753, #11158, #11863, #12084, #12452, #12638, #12708, #13747, and PRs #11997, #13847
- Key names in the namespace table were read from the safetensors headers of published LoRA files on Hugging Face: nerijs/pixel-art-xl, ByteDance/Hyper-SD, multimodalart/flux-tarot-v1, XLabs-AI/flux-RealismLora, terminusresearch/flux-lokr-garfield-nomask, mikaelh/qwen_image.lycoris-lokr.minecraft, lightx2v/Qwen-Image-Lightning, Kijai/WanVideo_comfy
Generating images locally? Take it further.
From FLUX and ComfyUI setup to building real image pipelines and apps. First chapter free, no card.
Go from one-off images to a real workflow
The Local Image Generation course covers ComfyUI, SDXL and FLUX properly — plus 24 more courses on running AI on your own hardware.
Liked this? 20 full AI courses are waiting.
From fundamentals to RAG, agents, MCP servers, voice AI, and production deployment with real GitHub repos. First chapter free, every course.
Build Real AI on Your Machine
RAG, agents, NLP, vision, and MLOps - chapters across 25 courses that take you from reading about AI to building AI.
Want structured AI education?
25 courses, 519+ chapters, from $9. Understand AI, don't just use it.
Continue Your Local AI Journey
- PILLARRun FLUX.1 Locally in 2026: VRAM Needs + 5-Minute Setup
- AI-Toolkit LoRA Training: FLUX.2, Z-Image & Qwen-Image
- Best GPU for Local AI Image Generation (2026): Ranked
- Best Local AI Image Models 2026: FLUX vs SDXL vs Qwen
- Chroma Local Guide: The Apache-2.0 Uncensored FLUX Model
- ComfyUI FLUX Workflow (2026): JSON Nodes Explained
- ComfyUI Missing Node Types: Fix a Red Workflow
- ComfyUI on Mac: MPS Errors and What Fixes Them
- ComfyUI Setup Guide: Install, Workflows, ControlNet, Flux
- Expected All Tensors on the Same Device: ComfyUI Fix
Comments (0)
No comments yet. Be the first to share your thoughts!