MapRoute Load Mapper
A text-encoder scalpel for SD1.x, if you bring the weights
- clip
- CLIP
The name is the pitch: MapRoute (a CVPR 2026 paper) is a "concept erasure" method, and this node is how you load one of its trained Mappers into a ComfyUI workflow. In plain terms: instead of fighting a concept with a longer negative prompt, a small neural network sits inside your text encoder and reroutes that concept's embedding somewhere harmless the moment it appears. In practice this is a research tool with training-code strings attached - you bring the .pth, the node does the injection. If you have (or trained) a Mapper, it's a genuinely surgical way to excise one thing. If you expected a plug-and-play filter, set that expectation down now.
How it works
Under the hood the node is doing one clean trick, and the code is honest about it. You feed it a clip from a Checkpoint Loader, it calls clip.clone(), then monkey-patches only that clone's text-encoder forward pass: wrap it in the Mapper's MLP, run your tokens through, restore the original forward in a finally block. The Mapper itself is a compact 768 → 1536 → 1536 → 768 MLP with GELU activations, a LayerNorm, and a residual connection - about 3.5M parameters. It takes the CLIP-L hidden state (the 768-dim vector that SD1.x actually conditions the UNet on) and nudges it before it ever reaches the sampler.
That clone-first design is the part worth appreciating. Because the patched CLIP is a separate object, the original from your checkpoint is untouched - exactly what makes the README's A/B test work: two CLIP Text Encode paths off the same loader, same seed, same prompt, one through the Mapper and one not. It's also why the shared cond_stage_model never gets permanently mutated for the rest of your graph.
The 768-dimensional input is also the hard constraint: that's the SD1.x CLIP-L signature, so this is a SD1.x-only feature. It has never been tested against SDXL's dual CLIPs or Flux's T5, and the README says so outright. It's the same fragility that killed negative embeddings when the encoder changed - a mapper bound to one encoder's dimensionality dies the moment the architecture does. Don't wire it into an SDXL graph and hope.
The inputs and outputs that matter
Only two inputs, and the dropdown is the one you'll actually touch:
clip- the CLIP from your Checkpoint Loader.mapper_file- a dropdown that lists every.pthsitting inComfyUI/models/maproute/. If it's empty, that's a folder problem, not a node problem (more below).
The single output is a CLIP, wired into your CLIP Text Encode node. That's the whole interface. The author's known-limitation section is refreshingly blunt: because the paper's "Router" part isn't implemented here, each node loads exactly one Mapper.
Installing it
ComfyUI Manager can find it - search for maproute-comfyui (or MapRoute). Or the manual way:
cd ComfyUI/custom_nodes/
git clone https://github.com/ningzh-h/maproute-comfyui.git
then restart ComfyUI. Note the README's own install snippet is a broken template - it has a [your-username] placeholder and a mismatched repo name, so trust the line above. Good news on dependencies: there's no requirements.txt at all; the node only needs torch and ComfyUI's own folder_paths, which you already have. On startup it registers a maproute model folder, so drop your trained .pth files in ComfyUI/models/maproute/ and restart.
Where people get burned
- Empty
mapper_filedropdown. The list is scanned at startup. Weights not inmodels/maproute/, or added after ComfyUI was already running, won't show. Drop the file in and restart. - "failed to load" in the console.
load_mapperaccepts either a raw state dict or a checkpoint dict with amodel_state_dictkey. Anything else - a training checkpoint that bundles optimizer state under a different key - silently fails, and the node just passes the unpatched CLIP through. - Wrong checkpoint family. Feed it an SDXL/Flux CLIP and it has no sensible 768-dim slot to patch. The console may not even scream at you; you just get no erasure. Check what your base model actually is before you chase ghosts.
- No weights at all. This is the honest trap: the repo ships zero Mapper weights. You need a trained
.pthfrom the companionmaproute-workspacetraining code, or from whoever published the concept erasure you're after. It's the difference between a tool you reach for and a paper implementation you experiment with.
The short version: on SD1.x with a trained Mapper in hand, this is a clean way to excise one concept without touching the UNet. Without those weights, the negative prompt still works fine - and needs no CVPR paper.
Inputs (2)
| Name | Type | Default | Description |
|---|---|---|---|
| clip | CLIP | — | |
| mapper_file | COMBO | 0 options: |
Outputs (1)
| Name | Type | Description |
|---|---|---|
| CLIP | CLIP | — |