MOSS-Image Official Sampler
Your KSampler Can't Run MOSS-Image, and That's the Feature
- dit
- conditioning
- latent
This is the node the whole pack exists for. Swap it for a KSampler and MOSS-Image still generates something - it just won't be the thing OpenMOSS trained. The pack is explicit about why: the official scheduler snaps your step count onto the training noise grid, and stock ComfyUI sampling has no concept of that grid, so the same seed and the same numbers give you a different image. If you care about matching the reference output, there is no substitute here.
How it works
The sampler isn't a reimplementation. It instantiates the pinned upstream MOSSImagePipeline with a MOSSImageScheduler configured from the DiT file's own embedded config, with your shift value folded in. That scheduler runs a Euler update in FP32 - noise, CFG combine and the latent updates are all computed in single precision even though the DiT itself runs bf16 - which is a small, boring, correct choice that keeps the trajectory from wandering on long runs.
Two more things happen under the hood that you should know about, because they're what a stock sampler can't do:
Real CFG. Default is 3.0, a genuine conditional/unconditional pass. This is genuinely nice in 2026, where most new models are guidance-distilled and run at CFG 1 with a dead negative prompt. MOSS-Image at CFG 3 means your negative box does something. See the Text Encode node for how far to push that.
Layer-level control. uncond_skip_layers defaults to "22", i.e. the unconditional branch skips layer 22 (zero-based) in the DiT. It's a documented default, not a bug, and it's how you'd go faster on the unconditional pass. slg_layers / slg_scale / slg_start / slg_stop are skip-layer guidance: off by default (slg_scale 0, empty list), and only worth touching if you're chasing the kind of composition problems SLG usually fixes. Both layer fields take a comma list or a JSON list, and any index outside the model's depth raises an error rather than being ignored - which is a kindness.
The inputs that matter
Wire it up: dit from the DiT Loader, conditioning from Text Encode, latent out to the Official VAE Decode. Nothing else accepts that output.
Defaults are 1024×1024, 50 steps, CFG 3, shift 5, seed 42, and they're sane - the author validated both variants on a canvas run at exactly these. The three you'll actually change:
steps - 50 is the reference setting. Don't port the "20 steps is plenty" habit from Z-Image or Klein; those are distilled for short schedules and this isn't, the same way older flow-matching advice keeps failing on newer models.
shift - the flow-matching timestep shift, the knob that replaced scheduler-picking. It biases effort between composition and detail, and it is model-specific. 5 is what this model ships with; nudge it, don't overhaul it.
width / height - must be positive multiples of 16 (the node hard-errors otherwise; max 4096). That's not arbitrary fussiness: latents are packed at H/16, W/16 with 128 channels.
batch_size up to 16 is there if you have the VRAM and want the seed-lottery convenience. seed has the usual control-after-generate widget.
Install
ComfyUI Manager → search ComfyUI MOSS-Image T8 (publisher t8star) → restart. Or:
cd ComfyUI
git clone https://github.com/T8mars/Comfyui-Moss-Image-T8 custom_nodes/Comfyui-Moss-Image-T8
python -m pip install -r custom_nodes/Comfyui-Moss-Image-T8/requirements.txt
Grab the models preserving structure (hf download t8star/Moss-Image-Comfy --local-dir models --include "diffusion_models/*" --include "text_encoders/*" --include "vae/*"), keeping each .assets folder beside its weights. The sampler needs all three components present, since it's the node that actually materializes the DiT.
Where people get burned
"Connect MOSS-Image Official Text Encode conditioning." The conditioning socket is a custom type carrying positive/negative embeddings and their attention masks. A normal CLIP Text Encode output will not connect, and that's correct - MOSS embeds are variable-length, so masks matter.
A stale sampler node. The pack's node signatures are pinned to one version of the pipeline; if you loaded an old workflow JSON from a different MOSS integration, you can end up with fields that don't exist anymore. Delete and re-add the node to see the current inputs.
Cutting steps to save time. You'll get soft, undercooked images and blame the sampler. Try 50 first, then experiment downward; and if composition feels mushy rather than sharp, that's shift, not cfg.
Assuming a missing/reloaded model is cached. Components are released between encoding, sampling and decoding, and when the sampler starts you'll see the DiT load into VRAM then go away again. That reload is expected - it's what keeps peak memory low enough for a 24 GB card.
CUDA out of memory at 1024². The device policy is an admission heuristic (weights plus ~2 GB), and activations aren't in that estimate. It runs on a 24 GB card per the author's testing; that's a tested config, not a promise about yours.
Inputs (14)
| Name | Type | Default | Description |
|---|---|---|---|
| dit | MOSS_IMAGE_DIT | — | |
| conditioning | MOSS_IMAGE_CONDITIONING | — | |
| seed | INT | 420–18446744073709550000 | — |
| steps | INT | 501–1000 | — |
| cfg | FLOAT | 3.00–30 | — |
| shift | FLOAT | 5.00.01–100 | — |
| width | INT | 102416–4096 | — |
| height | INT | 102416–4096 | — |
| batch_size | INT | 11–16 | — |
| uncond_skip_layers | STRING | 22 | — |
| slg_layers | STRING | — | |
| slg_scale | FLOAT | 0.000–30 | — |
| slg_start | FLOAT | 0.000–1 | — |
| slg_stop | FLOAT | 1.000–1 | — |
Outputs (1)
| Name | Type | Description |
|---|---|---|
| latent | MOSS_IMAGE_LATENT | — |