self-hosted/ai
§01·recipe · image

Qwen-Image-2.1 on any RTX 4070 board: int8 ComfyUI install in 12 GB, 2K and image editing

imageintermediate12GB+ VRAMSep 23, 2026

This intermediate recipe sets up Qwen-Image-2.1 on the RTX 4070, needing about 12 GB of VRAM.

models
tools
prerequisites
  • NVIDIA RTX 4070 12GB (GDDR6 or GDDR6X board), Ada Lovelace, compute capability 8.9
  • ComfyUI v0.37.0 or newer: the v0.37.0 Windows portable (the nvidia build, not the cu126 one) or a git install
  • A CUDA 13 (cu130) build of PyTorch and an NVIDIA driver from the 580 branch or newer
  • Python 3.10 or newer for a git install (the portable ships 3.13)
  • 32 GB of system RAM suggested, not a measured floor: the three weight files are 16.096 GiB and what is not on the card is held in RAM
  • 18 GB of free disk for the int8 diffusion model, int8 text encoder and VAE (17.28 GB as Hugging Face counts it)
  • Research or evaluation use only: the Qwen Research License forbids commercial use of the weights

What You'll Build

A local Qwen-Image-2.1 setup on one RTX 4070 in ComfyUI, using the int8 files ComfyUI's own templates load: text-to-image at 1024×1024 and at the model's native 2048×2048, RGBA output with a real alpha channel, and instruction-based editing with reference images. Qwen-Image-2.1 is a 7B single-stream diffusion transformer (DiT) behind a Qwen3-VL-8B text encoder and a four-channel (RGBA) VAE, released on 2026-09-20 with support in ComfyUI core. On a 12 GB card the transformer is not the hard part: it is 6.758 GiB in int8. The text encoder is, at 8.709 GiB, and the two are never on the card whole at the same time.

The RTX 4070 has the fewest SMs of the three 12 GB AD104 cards: NVIDIA's spec table gives it 5,888 CUDA cores and 12 GB on a 192-bit bus, and lists it with either GDDR6 or GDDR6X memory. The fit on this page does not depend on which memory your board has, or on its die (a few boards use a cut-down AD103; see The card, below); it is the same as on the RTX 4070 SUPER and the RTX 4070 Ti. What differs is speed, and the only timings found are the 4070 Ti's (Results).

⚠️ Read the licence before you download 17 GB. The weights ship under the Qwen Research License Agreement. Section 1.i defines "Non-Commercial" as the only permitted use — it "shall mean for research or evaluation purposes only." — and section 2.a grants the licence "FOR NON-COMMERCIAL PURPOSES ONLY". The grant is worldwide and there is no clause excluding any territory (section 4.a only reminds you that export controls may apply); the restriction is on purpose, not on place. Section 4.b reaches outputs in one specific case: "If you use the Materials or any outputs or results therefrom to create, train, fine-tune, or improve an AI model that is distributed or made available, you shall prominently display “Built with Qwen” or “Improved using Qwen” in the related product documentation." Every repack on this page — Comfy-Org's int8 files included — is a derivative and carries the same terms. Section 2.b gives an address for a commercial licence; users on the vendor's discussion #7 report that mail to it bounces, the latest on 2026-09-22. This is a reader's summary of the text, not legal advice.

Hardware data: RTX 4070 (12 GB VRAM; ComfyUI reports 12,282 MiB = 11.994 GiB on Windows, 11,864 MiB on Linux) · int8 encoder 8.709 GiB + int8 DiT 6.758 GiB = 15.467 GiB, so they take turns · no timing on this card; the RTX 4070 Ti's are under Results · See benchmark data

ℹ️ What was measured, and by whom. Nothing on this page was measured by this site on an RTX 4070, and no timing on this card turned up in the searches listed under Results. The timings there are one user's on the RTX 4070 Ti — the full AD104, with 14 more SMs — and they are given as that card's, never as this one's. Every VRAM figure is derived — from byte counts, from ComfyUI's source at tag v0.37.0, and from the startup logs owners of this card posted in public bug reports — and the arithmetic is shown. The site's own measured runs of this install are on one RTX 5060 Ti 16GB, a Blackwell card and not this one (one rig, one operator, unreplicated; cu130 session, cu128 session). This page uses them in exactly one place, the cost of ComfyUI's cu130 warning (Troubleshooting), with the same label and links there. If you run it, post your numbers.

Requirements

ComponentMinimumThis recipe
GPU12 GB VRAM, NVIDIA, a CUDA 13 build of PyTorchRTX 4070 (12 GB) — not measured by this site; the budget below is derived (/contribute)
RAM32 GB suggested, not a measured floor— the three files are 16.096 GiB, and under the default loader whatever is not on the card is held in RAM. The one AD104 run with published timings (Results) had 64 GB of DDR5
Storage17,283,091,112 B = 16.096 GiB (int8 DiT + int8 encoder + VAE)— byte counts from the Comfy-Org tree API
SoftwareComfyUI ≥ v0.37.0, PyTorch cu130, driver ≥ 580

The card: what the RTX 4070 brings, and what it does not change

RTX 4070Source
Architecture and dieAda Lovelace; AD104 with 46 of the die's 60 SMs enabled; some partner boards carry a cut-down AD103 insteadNVIDIA spec table (architecture); Tom's Hardware, 29 April 2024 (dies)
CUDA cores / SMs5,888 / 46 (at 128 cores per SM)NVIDIA; cores per SM from the Ada whitepaper
Boost clock2.48 GHzNVIDIA
Memory12 GB GDDR6 or GDDR6X, 192-bitNVIDIA
Host linkPCI Express Gen 4 (the page gives no lane count)NVIDIA
Board power200 W (Total Graphics Power)NVIDIA
Compute capability8.9NVIDIA's CUDA GPU list
Capacity ComfyUI reports12,282 MiB on Windows (12,878,086,144 B = 11.994 GiB unrounded); 11,864 and 11,880 MiB in the two 2026 Linux logs foundstartup logs, below

Which RTX 4070 you have does not change this page. NVIDIA's table lists the card with either GDDR6 or GDDR6X; the memory type changes bandwidth, not capacity or bus width. Some partner boards — MSI's Ventus 3X E 12G OC is the one Tom's Hardware names — carry a cut-down AD103 instead of AD104, at the same specification. Every figure below depends only on capacity, bus width and compute capability, which are the same either way.

Against the RTX 4070 SUPER (56 SMs, 220 W) and the RTX 4070 Ti (60 SMs, 285 W), this card has the fewest SMs and the lowest power of the three 12 GB AD104 cards (the SM counts are NVIDIA's core counts at 128 per SM, and Tom's Hardware gives the same 60, 56 and 46). Capacity, bus width, host link and compute capability are the same on all three, and those are all the memory figures on this page depend on, so the fit below is the same on all three; the differences can only show up as speed.

The capacity that matters is the one the driver reports, not the one on the box. ComfyUI prints it at startup as Total VRAM … MB, and the figure is MiB. This page read the 31 startup-log excerpts naming an RTX 4070 that turned up in issues on the ComfyUI tracker. 26 read 12,281 or 12,282 MiB, and every one of those whose OS can be told from its paths or its Python build is Windows (23; the other 3 carry no OS evidence); the newest is from 2026-06-13 on Windows 11 (#14448), and the system-information block of a May 2026 one on Windows 10 with PyTorch 2.10.0+cu130 (#13750) gives the unrounded total, 12,878,086,144 B = 11.994 GiB. Five read 11,864–11,980 MiB, and the four of those with OS evidence are Linux; the two from 2026 are 11,880 MiB on CachyOS with driver 610.43.03 (#15125, July) and 11,864 MiB on a GCC-built Python with comfy-aimdo's POSIX build (#15816, August). No log says why Linux reads lower. This page budgets Linux against the lower of the two 2026 readings, 11,864 MiB = 11.586 GiB (the log rounds to the MiB). Whatever drives your display and the CUDA context then come out of whichever figure applies.

The files

The three files the official templates load, byte-exact from the Comfy-Org repack's tree API at revision 5dc5850e (2026-09-22, a README edit; every weight file's size and LFS hash is the same as at the previous revision ace0edeb). This is launch week: re-check the sizes before you rely on them.

FileBytesGiBDestination
diffusion_models/qwen_image_2.1_int8_convrot.safetensors7,256,783,0646.758models/diffusion_models/
text_encoders/qwen3vl_8b_int8_convrot.safetensors9,350,798,3608.709models/text_encoders/
vae/qwen_image_2.1_vae_bf16.safetensors675,509,6880.629models/vae/

The same repo holds a bf16 DiT (14,230,280,616 B = 13.253 GiB, bigger than this card on its own), a bf16 encoder (17,534,334,616 B = 16.330 GiB), a w4a8 encoder (6,312,105,364 B = 5.879 GiB — the one alternative that matters on 12 GB) and two qwen3.5_9b_…_pe_… files, which are prompt enhancers, not encoders. Its recursive tree lists exactly two DiT files, bf16 and int8; there is no fp8 or nvfp4 DiT in it. The ComfyUI docs page for this model was synced to the templates on 2026-09-22 (docs commit 9d133794) and now lists the int8 encoder as the one "loaded by the templates, lower memory" and the bf16 one as full precision. Follow it: the bf16 encoder cannot be resident on this card at all.

min_vram_gb is 12, the smallest card size in this catalogue on which every stage of this install keeps its weights whole under both of ComfyUI's loaders; the derivation is on this model's RTX 3060 page, and the tables below re-check it against what this card actually reports.

What actually gates this card

ComfyUI has two loaders, and they budget VRAM differently. On this card the default is DynamicVRAM: main.py at v0.37.0 enables it on any NVIDIA device once PyTorch is 2.8 or newer and comfy-aimdo initialises. You land on the legacy estimate-based loader instead if you pass --disable-dynamic-vram (or --highvram, --gpu-only, --novram, --cpu), or if the startup log says Falling back to legacy ModelPatcher. Both views below come from ComfyUI's source at tag v0.37.0 (comfy/model_management.py, comfy/sampler_helpers.py, comfy/model_base.py, comfy/sd.py, comfy/model_patcher.py), from comfy-aimdo v0.5.5 (the version requirements.txt pins), and from the byte counts above, summed unrounded and rounded once. Every "left" figure is against the per-OS capacity figure set out under The card, above, and the desktop's share and the CUDA context still have to come out of it.

Two of ComfyUI's planning figures appear below; neither is a peak anyone read off nvidia-smi:

  • The sampler's activations. area × dtype_size × 0.01 × memory_usage_factor MiB, with memory_usage_factor = 6.0 for this model in comfy/supported_models.py and area the latent grid times the batch: 64×64 at 1024², 128×128 at 2048². The source carries the comment "this needs to be tweaked". comfy/sampler_helpers.py computes it twice: at a doubled batch (noise_shape[0] * 2), which is ComfyUI's estimate — 0.960 GiB at 1024², 3.840 GiB at 2048², even at cfg 1 — and at the real batch, a separate minimum — 0.480 GiB and 1.920 GiB.
  • The VAE decode. For this VAE comfy/sd.py estimates 900 × h × w × 256 × dtype_size bytes over the latent grid: 1.758 GiB at 1024², 7.031 GiB at 2048².

DynamicVRAM (the default). ComfyUI's estimates do not govern this path: memory_required() in model_patcher.py says that with dynamic models it "is ignored and its all done dynamically", and ModelPatcherDynamic.partially_load() never uses the extra_memory it is handed. The floor is comfy-aimdo's, and it differs by OS. On Linux, src/plat.h defines VRAM_HEADROOM (256 * 1024 * 1024) and keeps that much free against the card's live free VRAM. The Windows build uses src-win/shmem-detect.c instead, which keeps 512 MiB free against both the WDDM budget and NVML's free-VRAM reading (96 MiB if it falls back to cuMemGetInfo). Its budget takes the larger of that live check and a second one against the card's total capacity. --reserve-vram N feeds only the second — comfy-aimdo's own control.py says raising it above 256 MB is honoured and lowering it changes nothing — and --vram-headroom N adds N GiB on top of both. Weights are loaded on demand and evicted when an allocation needs the room; the comfy-aimdo README describes "on-demand offloading of model weights when the primary pytorch VRAM allocator comes under pressure". So a stage never fails for want of room for its weights; the table says whether they can stay whole for the stage or have to be evicted and re-read part-way.

Stage (DynamicVRAM)WeightsWeights + aimdo floor, Windows (0.5 GiB)Left of 11.994 GiBWeights + aimdo floor, Linux (0.25 GiB)Left of 11.586 GiB
Text encode, int8 encoder8.709 GiB9.209 GiB2.785 GiB8.959 GiB2.627 GiB
Text encode, w4a8 encoder5.879 GiB6.379 GiB5.615 GiB6.129 GiB5.457 GiB
Denoise, weights alone (any size)6.758 GiB7.258 GiB4.735 GiB7.008 GiB4.578 GiB
Denoise at 2048², + the batch-1 activation minimum (1.920 GiB)8.678 GiB9.178 GiB2.815 GiB8.928 GiB2.658 GiB
Denoise at 2048², + ComfyUI's doubled estimate (3.840 GiB)10.598 GiB11.098 GiB0.895 GiB10.848 GiB0.738 GiB

The dynamic loader reserves nothing for the VAE decode. At v0.37.0 the VAE is a dynamic model too, free_memory() with for_dynamic=True does not unload one dynamic model to make room for another (its comment reads "don't actually unload dynamic models for the sake of other dynamic models"), and past that call the decode estimate only sizes the decode batch (comfy/sd.py). DiT weights leave the card during a decode only if the decode's own allocations need the room, and no measurement of how large those are at 2K on an AD104 card turned up.

Legacy loader (only if you are on it). Here the reserve is real. minimum_inference_memory() is 0.8 GiB plus EXTRA_RESERVED_VRAM, which model_management.py (lines 877–881) sets to 400 MiB, to 600 MiB on Windows, and to 100 MiB more only when the card reports over 15 × 1024 MiB — so a 12 GB card gets 1.191 GiB on Linux and 1.386 GiB on Windows. load_models_gpu() loads a model whole only if what is free, less the larger of that reserve and the stage's own minimum plus EXTRA_RESERVED_VRAM (for the sampler, the batch-1 activation figure; for the decode, the decode estimate), still holds it; otherwise it loads it partially. The totals are those residency thresholds:

Stage (legacy loader)WeightsThreshold, WindowsLeft of 11.994 GiBThreshold, LinuxLeft of 11.586 GiB
Text encode, int8 encoder (the 2.1 encoder carries no estimate, so the reserve applies)8.709 GiB10.095 GiB1.899 GiB9.899 GiB1.687 GiB
Text encode, w4a8 encoder5.879 GiB7.265 GiB4.729 GiB7.069 GiB4.517 GiB
Denoise at 1024² (0.480 GiB + the OS reserve is below the reserve on both OSes)6.758 GiB8.144 GiB3.849 GiB7.949 GiB3.637 GiB
Denoise at 2048² (1.920 GiB + 600 MiB on Windows, + 400 MiB on Linux)6.758 GiB9.264 GiB2.729 GiB9.069 GiB2.517 GiB
VAE decode at 1024², DiT still on the card7.387 GiB9.731 GiB2.262 GiB9.536 GiB2.050 GiB
VAE decode at 2048², DiT partly unloaded to make room (kept whole: 15.005 / 14.809 GiB, past the card)0.629 GiB8.246 GiB3.747 GiB8.051 GiB3.535 GiB

Before loading, the legacy loader also unloads other models until 1.1 × the incoming weights plus the larger of the reserve and ComfyUI's doubled estimate plus EXTRA_RESERVED_VRAM is free. At 2048² sampling that target is 11.860 GiB on Windows and 11.665 GiB on Linux — more than the 11.586 GiB Linux figure this page uses, and within 0.133 GiB of the Windows one — so everything else leaves the card before a 2K sample, whatever else you had loaded.

Four things follow.

The encoder and the DiT never sit on the card whole at the same time. Together they are 16,607,581,424 B = 15.467 GiB, against 11.994 GiB on Windows; even with the w4a8 encoder the pair is 13,568,888,428 B = 12.637 GiB, still past the card before any floor. Under DynamicVRAM ComfyUI does not unload one of them for the other; comfy-aimdo evicts weights as allocations need the room. The practical consequence is an inference from the arithmetic, not a measurement: a new prompt re-runs the encoder, so its weights have to come back onto the card, and the DiT's have to come back when sampling starts. On a 16 GB RX 9070 XT the reporter of #16437 describes the same pressure one tier up: "The 7B DiT (6920 MB staged) plus the qwen3vl_8b text encoder (8916 MB staged) cannot co-reside in 16304 MB." Those two figures are the files' sizes in MiB, not peaks.

The encoder stage is the binding one for weights in both views: 9.209 GiB under DynamicVRAM on Windows (8.959 GiB on Linux), 10.095 GiB under the legacy loader on Windows (9.899 GiB on Linux). At 2048² the sampler's activations can come close to it or pass it: with the batch-1 minimum the denoise stage is 9.178 GiB on Windows, and with ComfyUI's doubled estimate 11.098 GiB, leaving 0.895 GiB of the card — planning figures the dynamic loader does not use, but the only ones there are. Neither loader budgets the encoder's own activations, so an edit with several large reference images — which all pass through the encoder's vision tower — has an unestimated working set on top.

Why 12 GB is the floor for this install. On 8 GB the int8 encoder's 8.709 GiB cannot stay whole at all, so DynamicVRAM would evict and re-read it part-way through every encode; the RTX 5060 page in this series documents the 8 GB install (the w4a8 encoder). On this card every stage in both tables keeps its weights whole on both OSes, the thinnest threshold being the legacy int8 encode (1.899 GiB left on Windows, 1.687 GiB on Linux) — before the desktop and the CUDA context.

At 2K the decode is what is tight. On the legacy loader the 2048² decode asks for 7.031 GiB plus the reserve and the DiT cannot stay beside it whole (15.005 GiB on Windows, 14.809 GiB on Linux, both past the card), so the loader partly unloads the DiT until 1.1 × the VAE plus that much is free — 8.309 GiB on Windows, 8.114 GiB on Linux — which leaves at most 3.684 GiB of it on the card on Windows and 3.472 GiB on Linux, before the desktop and the CUDA context; the unloaded part is loaded again for the next image. On the default loader nothing is reserved and DiT weights are evicted only if the decode needs the room. Either way ComfyUI keeps a fallback for a decode that runs out: it logs "Warning: Ran out of memory when regular VAE decoding, retrying with tiled VAE decoding." and tiles it. So 2K should complete; the one 2K-class AD104 timing this page uses is in Results.

Installation

1. ComfyUI v0.37.0 or newer, on a cu130 PyTorch

Support is in ComfyUI core, not a custom node: PR #16400 (author kijai, merged 2026-09-19), and tag v0.37.0 contains it. The v0.37.0 release, with Windows portable builds, was published at 07:35 UTC on 2026-09-21. A v0.37.1 tag followed at 19:12 UTC on 2026-09-22; read again on 2026-09-23 around 06:10 UTC it had no release object and no portable of its own, so v0.37.0 was still the latest release. Its three commits add Hunyuan Image 3.5 partner nodes, move the workflow templates to 0.11.68 (which adds the Hunyuan templates and translated titles for the 2.1 background-removal template) and bump the version; none of them changes the model's code or any of the three 2.1 workflow files, which are unchanged since templates commit 371a7b7171. A backport pull request for that tag, #16467, was closed unmerged. This page pins v0.37.0 because it is the one with a portable build.

Windows portable. Take ComfyUI_windows_portable_nvidia.7z from the v0.37.0 release. The ComfyUI README says "The portable above currently comes with python 3.13 and pytorch cuda 13.0." — which is the build this card needs. Do not take ComfyUI_windows_portable_nvidia_cu126.7z: the README labels it for 10-series and older cards, adding "DO NOT USE THIS ON NEWER 20 SERIES AND ABOVE GPUS", and on this card a CUDA 12 build switches off the fast int8 kernels (step 2).

Git (Linux; on Windows use the portable, or swap the activation line as noted in the block). Install PyTorch from the cu130 index first, then the requirements — the torch line in requirements.txt is unpinned, so the order decides which build you get:

git clone https://github.com/Comfy-Org/ComfyUI
cd ComfyUI
git checkout v0.37.0
python -m venv venv
source venv/bin/activate    # Windows cmd/PowerShell: venv\Scripts\activate
pip install torch torchvision torchaudio --extra-index-url https://download.pytorch.org/whl/cu130
pip install -r requirements.txt
python -c "import torch; print(torch.__version__, torch.version.cuda, torch.cuda.get_device_capability())"

The print must show a +cu130 torch, 13.0, and (8, 9) — Ada's compute capability, which NVIDIA's CUDA GPU list gives for the RTX 4070. The README states the requirement as policy — "Using a cu130 or above version of pytorch is required on Nvidia 20 series and above." — and a CUDA 13 build needs an NVIDIA driver from the 580 branch or newer, the minimum NVIDIA's CUDA release notes give for CUDA 13.x. requirements.txt at the tag pins comfy-kitchen==0.2.35, comfy-aimdo==0.5.5 and comfyui-workflow-templates==0.11.66; the last is the templates release that switched the Qwen-Image-2.1 templates to the int8 encoder. Leave this shell open with the venv active: step 3 runs in it.

Tag or master? Two follow-up PRs merged after the tag and are on master only: PR #16429, which changes where the edit path's K/V cache is placed — it matters on a card this full, see Editing below — and PR #16430, which compiles the 2.1 transformer blocks. v0.37.0 is the safer default, because master also carries the code in an open crash report on image editing, #16443, and a second hard-abort report, PR #16481, whose stack matches master; the tag is not proven immune to the second (Troubleshooting has both).

2. What Ada gets from the int8 files, and what it does not

Both int8 files carry, per layer, the quantisation format int8_tensorwise with convrot: true and a group size of 256 (read from each file's safetensors header). What happens to those weights differs between the two models.

For the diffusion model, ComfyUI decides per device which formats run natively in get_disabled_quant_formats() in comfy/ops.py, and prints the result when it loads the model. For compute capability 8.9 the checks in model_management.py resolve like this: supports_fp8_compute() is True (major 8, minor 9), supports_nvfp4_compute() and supports_mxfp8_compute() are False (they want major 10 or higher), and supports_int8_compute() is True. An RTX 4070 SUPER owner's log on the ComfyUI tracker (#15528, 2026-08-12, ComfyUI 0.32.0 on PyTorch 2.13.0+cu130) prints exactly that split: Native ops: convrot_w4a4, float8_e4m3fn, asym_w4a8_int8, float8_e5m2, int8_tensorwise , emulated ops: nvfp4, mxfp8. v0.37.0 defines the same formats and the same checks, so it prints the same split; the order of the names varies between runs. An emulated layer's weight is dequantised to bf16 for the matmul.

For the text encoder that table does not apply. At v0.37.0 every quantised encoder is built with mixed_precision_ops(..., full_precision_mm=True) in comfy/sd1_clip.py, so each weight is dequantised for its matmul on every card. The one call that switches quantised matmuls back on, use_quantized_matmul, wraps only LLM text generation, not the conditioning encode this model uses. The encoder's file format is therefore a memory choice, not a speed choice. Three consequences:

  • The int8 DiT is the right file here, not a compromise. Its matmuls run as INT8 GEMMs. With a cu130 PyTorch, the comfy-kitchen CUDA backend rotates and quantises the activations in one fused kernel and runs the GEMM through its CUTLASS INT8 path, which its source (backends/cuda/__init__.py, pinned at the commit tagged v0.2.35) enables for compute-capability major 8 and above — Ada included, through the same code as Blackwell.
  • Without cu130 nothing breaks; it runs the slow way. The gate is in comfy/quant_ops.py: below CUDA 13 it calls ck.registry.disable("cuda") and logs "WARNING: You need pytorch with cu130 or higher to use optimized CUDA operations." comfy-kitchen then falls through to its eager backend, whose int8_linear applies the Hadamard rotation as ordinary torch ops, quantises the activations per row and still multiplies through torch._int_mm. That is a working INT8 path with the fusion gone — not a dequantisation to bf16, and not a failure. It is also why the Native ops line will not warn you: it reflects the hardware, not which comfy-kitchen backend is alive.
  • For the encoder, pick by size. Comfy-Org's encoder repo Comfy-Org/Qwen3-VL also holds qwen3vl_8b_fp8_scaled.safetensors (10,588,637,512 B = 9.861 GiB) and qwen3vl_8b_nvfp4.safetensors (6,305,221,764 B = 5.872 GiB). This card's FP8 cores do nothing for the fp8 file, because the encode dequantises it like any other; it is 1.153 GiB larger than the int8 file. The nvfp4 file is within 7 MB of the w4a8 encoder that ships beside the int8 one. No report of either being run with 2.1 turned up (Results lists where this page looked). If the encoder stage is what you need to shrink, take w4a8 — it saves memory, not time.

Why the encoder identity matters: Comfy-Org's qwen3vl_8b_bf16.safetensors in the 2.1 repo carries the same LFS sha256 as the file of that name in Comfy-Org/Qwen3-VL, a repo that held it months before the 2.1 weights were public, and two users on the vendor's discussion #5 report comparing its tensors with the stock Qwen3-VL-8B-Instruct and finding no further training. No Qwen member says so in that thread. It is why encoder quants from the older repo are interchangeable in principle.

3. Download the weights

The repo's folder names match ComfyUI's models/ layout, so --local-dir models lands each file where the loaders look. Pinned to the revision whose byte counts are above; run it from inside the ComfyUI folder with the venv active:

pip install -U huggingface_hub
hf download Comfy-Org/Qwen-Image-2.1 \
  diffusion_models/qwen_image_2.1_int8_convrot.safetensors \
  text_encoders/qwen3vl_8b_int8_convrot.safetensors \
  vae/qwen_image_2.1_vae_bf16.safetensors \
  --revision 5dc5850eb514a3685f6a03a2641728a8f7549c69 --local-dir models

On the Windows portable there is no pip or hf on PATH. Use the Python the portable ships, python_embeded\python.exe — the interpreter its run_nvidia_gpu.bat starts ComfyUI with and its updater runs pip through — from the portable's top folder, the one holding python_embeded and ComfyUI:

python_embeded\python.exe -s -m pip install -U huggingface_hub
python_embeded\python.exe -s -m huggingface_hub.cli.hf download Comfy-Org/Qwen-Image-2.1 diffusion_models/qwen_image_2.1_int8_convrot.safetensors text_encoders/qwen3vl_8b_int8_convrot.safetensors vae/qwen_image_2.1_vae_bf16.safetensors --revision 5dc5850eb514a3685f6a03a2641728a8f7549c69 --local-dir ComfyUI\models

(-m huggingface_hub.cli.hf is the module behind the hf command; it runs directly because cli/hf.py ends in a __main__ guard.)

Check the bytes against the LFS hashes in the tree; on Windows, certutil -hashfile <file> SHA256 prints the same hash. A truncated download is the likeliest cause of a load error (Troubleshooting):

sha256sum models/diffusion_models/qwen_image_2.1_int8_convrot.safetensors
# cb74113cb03faecd79611b01fd7fd642f0aa60d6f0b95086abee214d75eaa57d
sha256sum models/text_encoders/qwen3vl_8b_int8_convrot.safetensors
# 8bfd0f6e12abf2d2d697ecc888e5e90b0d6741d6708f05799f53afa560452e8f
sha256sum models/vae/qwen_image_2.1_vae_bf16.safetensors
# bb21f7473051e1ac368515dd3f2e15cd44d7a11748ee8823e1ddca3e4876b7c9

If you settle on the smaller encoder, the fourth file is text_encoders/qwen3vl_8b_w4a8.safetensors from the same repo and revision — select it in the template's CLIP loader. Do not confuse it with the two qwen3.5_9b_qwen_image_2.1_pe_*.int8_convrot.safetensors files beside it: those are Qwen3.5-9B prompt-rewriting models for an optional LLM stage, and a user on the repack's discussion #4 who swapped one in as the text encoder got garbled images. At 9,471,072,252 B each they are another encoder-sized load on a card that already cannot hold one beside the DiT; skip them here.

4. Start ComfyUI and read the log

python main.py in the same shell; on the portable, run_nvidia_gpu.bat. No --lowvram, no --reserve-vram: --lowvram is documented in comfy/cli_args.py as "Doesn't do anything if dynamic vram is enabled." On this card the first screen should show:

  • Total VRAM 12282 MB on Windows (the two 2026 Linux logs found read 11,864 and 11,880). A figure near 16,376 means a 16 GB card, not this one.
  • pytorch version: ending in +cu130, and no cu130 warning.
  • Found comfy_kitchen backend cuda: with 'available': True, 'disabled': False. An RTX 4070 Ti owner's Windows log from 2026-09-23 (#16490, PyTorch 2.13.0+cu130) shows that line in this state. 'disabled': True means the backend is installed and switched off — the cu130 gate — so checking available alone proves nothing.
  • DynamicVRAM support detected and enabled, and ComfyUI version: 0.37.0 or higher.

When the diffusion model loads, ComfyUI prints Using mixed precision operations and the Native ops: … line from step 2. You do not need a flag for the desktop: comfy-aimdo's live check keeps its floor free after whatever the desktop already holds. If you want more kept free anyway, --vram-headroom N adds N GiB on top of both of its checks; --reserve-vram N is weaker under DynamicVRAM, and it is also what the legacy loader uses as its reserve.

Running

Text-to-image

Open the Template Library and load Qwen Image 2.1: Text to Image (image_qwen_image_2_1_t2i.json, workflow templates v0.11.66, the version v0.37.0 pins). The values that govern it sit on the outer subgraph node: UNETLoaderqwen_image_2.1_int8_convrot.safetensors, CLIPLoaderqwen3vl_8b_int8_convrot.safetensors with type qwen_image, VAELoaderqwen_image_2.1_vae_bf16.safetensors, 25 steps, cfg 1, euler / simple, 1024×1024. The int8 files are ComfyUI's own default, not a low-VRAM workaround. The template's note explains the setting people change first: "negative_prompt: unused while cfg is 1." At cfg 1 ComfyUI skips the negative pass; the note also says "cfg: keep 1 for the Qwen Image 2.1 official path. Raise it only if you use a negative prompt.", and raising it adds a second model pass on every step. The template's own note on the Desktop app: "Desktop/Cloud updates follow stable releases, so some nightly-supported models may not be available yet."

Expect the first run to encode the prompt, sample, then decode. Re-queue with only the seed changed and the encode does not repeat, because ComfyUI caches the conditioning. Change the prompt and the encoder has to come back onto the card, then the DiT after it; no published figure isolates how long that takes on an RTX 4070.

Native 2K. The note says "For native 2K, set 1:1 and 4 megapixels" in the Resolution Selector. The sampling schedule does not follow the resolution: ComfyUI fixes Qwen-Image-2.1's shift at 0.69 at every size (supported_models.py), while the vendor's scheduler_config.json turns on dynamic shifting. Issue #16447 (open) reports the mismatch; a ComfyUI maintainer replied on 2026-09-22 that the fixed shift is "kind of on purpose", because "the higher the shift the more you see a grid pattern which is very obvious in your first image", and another user disagreed the same day. The 2K decode is where the budget is tightest (What actually gates this card).

Transparent output. The vendor README's prompt form is "This is an RGBA image with transparency. A cute cartoon dragon sticker. The image has alpha channel and the background is transparent." Replace the middle sentence with your subject, and keep the template's SaveImageAdvanced at PNG; JPEG throws the alpha away.

Steps. The vendor's diffusers example runs 40 steps; the template's 25 is ComfyUI's choice, not Qwen's. A step-distilled option for 2.1 appeared on 2026-09-22: Viggle/Qwen-Image-2.1-viggle-turbo, a third-party 4-step distillation by Viggle, shipped as a rank-64 LoRA and as a full bf16 transformer and labelled a v0.1 preview. Its card says the release "still falls short of the base model": text-to-image at 4 steps is usable, complicated edits are clearly worse. The card documents diffusers only, with its own scheduler setting, and names no ComfyUI workflow; nothing on this page was run with it. Late on 2026-09-22 a community repo, realrebelai/Viggle_Qwen-Image-2.1-Turbo_GGUFs, gained six GGUF conversions of that full transformer (Q2_K at 3,773,873,248 B to Q8_0 at 7,687,158,880 B) for ComfyUI-GGUF; its README says that in its author's tests the GGUFs did not reproduce the upstream transformer's output exactly, even at BF16-equivalent precision. Not run here either.

Editing with reference images

Load Qwen Image 2.1: Image Edit (image_qwen_image_2_1_image_edit.json, same release). Same three loaders, plus a TextEncodeQwenImage21 node with the VAE connected — each reference is seen by the encoder's vision tower and spliced into the sequence as latents — and a QwenImage21Cache node at auto / default. The text and reference tokens are the same on every step, so their attention K/V are computed once and cached; the cache node's tooltip in comfy_extras/nodes_qwen.py says "auto uses spare VRAM, then RAM. cpu (RAM) is prefetched behind compute and costs little speed."

On a 12 GB card, where the cache lands decides the speed. comfy/ldm/qwen_image21/model.py sizes it as 2 × 32 layers × prefix tokens × 4096 × 2 bytes. At the resolution 1056 this page recommends below, the template's two 896×1152 references become 928×1184 each, 8,584 latent tokens: 4,500,488,192 B = 4.191 GiB, or 2.096 GiB at dtype int8, plus 524,288 B per prompt token. At v0.37.0, auto keeps it on the GPU only if four times that size is free at the moment of the check, then tries system RAM under the same rule, and otherwise recomputes the whole prefix on every step. Four times even the int8 cache is 8.383 GiB, and with the DiT on the card no more than 5.235 GiB of this card's Windows capacity can be free, so on 12 GB the GPU leg cannot pass while the DiT is resident, and auto falls to RAM — 8.383 GiB of free RAM for the int8 cache, 16.766 GiB for the default one. The author of PR #16429, which relaxes the check on master only, lists two problems with it: "It requires the VRAM to be free at the time of the check to use VRAM mode which gets disrupted by smart memory + dyn vram" and "It requires 4x RAM to be free and doesnt account the pin quotas at all". On that PR's test machine ("Windows, RTX5080, 32GB RAM, fast disk" — a 16 GB Blackwell card, not this one) a two-reference edit went from the full-recompute fallback at 4.01 s/it to 1.02 it/s.

What to do on v0.37.0, derived from the node's code and not measured on this card: set the cache node's dtype to int8 — its tooltip says "int8 halves the cache at about bf16 accuracy" — and device to cpu, which skips the four-times test and asks only for twice the cache free in RAM (4.191 GiB for the int8 cache at resolution 1056). Moving to master for PR #16429 is the other route, but master carries the edit crash of #16443 (Troubleshooting).

Set resolution to 1056 before you edit. The template sets it to 0, and its note says "This template starts at 0: no resize beyond a multiple of 32." That default interacts with an open defect, #16435, in which certain reference grids render the edit broken, and its two reports disagree on which:

  • The original reporter (Apple MPS and CPU, bf16 files) gets broadband speckle when the grid comes out at exactly 1024: "Composition and identity are correct; only the rendering is degraded." 512, 992 and 1056 are clean, and the reporter's follow-up says "the template's 0 is equally affected whenever the first reference image is 1024×1024".
  • A second commenter (an RTX 5070 Ti on v0.37.0 with cu130 and the bf16 DiT) finds a 1024×1024 reference clean but a 1536×1024 one broken at resolution 0 and at 1248, with the edit instruction ignored; 512, 1024, 1056 and 2048 are clean there. The setups differ in encoder precision, reference image, step count, OS, build and attention path, so neither report isolates a cause.

512 and 1056 are clean in both, and 512 shrinks each reference to a quarter megapixel, so use 1056. The issue was still open on 2026-09-23 with no comment since 2026-09-21. PR #16444, a proposed fix, was closed without merging on 2026-09-22 by kijai; no fix is linked to #16435 now. Neither report names an AD104 card.

Smaller builds: what they change on 12 GB

The binding stage on this card is the text encoder, so a smaller transformer alone does not move the ceiling; the encoder is the lever (w4a8, above). What a smaller DiT changes is co-residence, and on 12 GB that is the one thing that would stop a prompt change from moving 8.7 GiB of encoder weights. None of what follows was run on this card or, as far as the searches in Results reach, on any AD104 card.

  • The w4a8 encoder plus a 4-bit-class DiT fit together. With toxicdog's INT4 ConvRot DiT (3,666,512,184 B = 3.415 GiB), the w4a8 encoder and the VAE come to 10,654,127,236 B = 9.922 GiB; with aimdo's floor that leaves 1.571 GiB of the Windows figure and 1.414 GiB of the Linux one for the activations (0.480 GiB batch-1 at 1024²), the CUDA context and the desktop. That DiT's header declares the convrot_w4a4 format, native on this card by the Native ops line above, and comfy-kitchen 0.2.35 enables its native 4-bit kernel only when the compute capability's major number is 8 (_cuda_device_supports_native_int4_mma) — Ampere and Ada, this card included. The only comment on that repo's discussion tab, from a user who names no card, reports poor output quality. It is a third-party quantisation of the same research-licensed weights.
  • GGUF DiTs start at Abiray's Q4_K_M, 4,189,343,904 B = 3.902 GiB, and go down to Q3_K_M at 3,185,944,736 B = 2.967 GiB; leejet's smallest, Q2_K, is 2,561,716,256 B = 2.386 GiB, and unsloth's set runs from Q2_K at 2,466,137,824 B = 2.297 GiB to Q8_0. ComfyUI-GGUF dequantises each weight to the compute dtype before the matmul, so these give up the INT8 GEMM, and a Q8_0 (Abiray's is 7,591,579,808 B = 7.070 GiB) saves nothing against the int8 file. They also take a different loader path: GGUFModelPatcher in city96's nodes.py subclasses ComfyUI's legacy ModelPatcher, whose is_dynamic() is False, so ComfyUI's free_memory() evicts a GGUF DiT the legacy way even with DynamicVRAM on. The co-residence arithmetic in the first bullet is for ComfyUI-format files such as the INT4 ConvRot build, not for GGUFs. Which loader takes which file is under Troubleshooting.
  • On the legacy loader, and for a GGUF DiT on either loader, a DiT small enough to stay whole beside the 2048² decode is not partly unloaded and re-read for every 2K image: the loader keeps 1.1 × the VAE plus the decode estimate plus its reserve free, which leaves room for a DiT of at most 3.684 GiB on Windows and 3.472 GiB on Linux, before the desktop and the CUDA context. The Q3-and-smaller GGUFs pass that (Abiray's Q3_K_M with 0.717 GiB to spare on Windows); INT4 ConvRot passes with 0.270 GiB on Windows and 0.057 GiB on Linux, too little to count on; of the Q4 files, only unsloth's Q4_K_S (3,906,356,960 B = 3.638 GiB) fits, on Windows only, with 0.046 GiB to spare.
  • Not for this card: NVFP4. The NVFP4 DiT builds (for example BennyDaBall's, 4,197,574,664 B) load, but supports_nvfp4_compute() wants major 10 or higher, so on Ada they are emulated: the memory saving survives and the kernel does not.
  • FP8 buys nothing in size, and the files found are not ComfyUI's format. Ada has FP8 tensor cores and ComfyUI lists float8_e4m3fn as native on it, but an FP8 DiT is as large as the int8 one (7.1 GB), so it would not change the fit. The FP8 DiT builds this page found — unsloth's Qwen-Image-2.1-FP8 and Rin247's — are published for diffusers. Unsloth's file, whose header this page read over HTTP range requests, stores torchao Float8Tensor entries (_weight_qdata, _weight_scale) under diffusers key names and carries neither the per-layer comfy_quant markers nor the scaled_fp8 key that ComfyUI's loader looks for in comfy/utils.py (Comfy-Org's int8 DiT carries 192 such markers). Comfy-Org publishes no FP8 DiT for 2.1. Not tried here.

Results

  • Speed: no timing on an RTX 4070 turned up. The only Qwen-Image-2.1 timings found on a 12 GB AD104 card are on the RTX 4070 Ti, the full AD104 (the RTX 4070 carries a cut-down AD104, or on some partner boards a cut-down AD103) with 14 more SMs (46 against 60) and the same 12 GB on a 192-bit bus. The Comfy with ComfyUI guide's Qwen-Image-2.1 page, by nomadoor, attaches a timing to each of its workflows, all on an RTX 4070 Ti 12GB with 64 GB of DDR5, all with the template's three int8 files at 25 steps, cfg 1, euler / simple, and each labelled "Measured after model unload and cache clear" — a cold start. Three of them bear on this page, as the RTX 4070 Ti's numbers, not this card's:

    The guide's workflowOutputSamplerEnd to end
    Text-to-image1664×2496 (2:3, about 4 MP)3.45 s/it121 s
    Text-to-image, RGBA prompt1440×1440 (about 2 MP)1.11 s/it65 s
    Image edit, one referenceabout 1 MP0.58 s/it57 s

    The output sizes are what ComfyUI's Resolution Selector computes from the workflows' own settings (2:3 at 4 MP and 1:1 at 2 MP, multiples of 32); the edit's output is the size of its input, which the guide resizes to about 1 MP beforehand. 25 steps at 3.45 s/it is 86 s of the 121 s; the rest is loading, encoding and decoding from cold. The guide's own design note (ADR) says these are reference figures, not a strict benchmark, and that CUDA, PyTorch, driver and launch arguments are not recorded, and the figures went up on 2026-09-22 — so neither the ComfyUI build nor whether the int8 layers ran on the cu130 kernels this page prescribes is known. No figure at the template's own 1024×1024 was published there. Other named-card timings found for this model are on other cards (RTX 4060 Ti 16GB, 5060 Ti, 5080, 4090, 5090); none is a 12 GB AD104 card, so none is used here. On the same software an RTX 4070, with fewer SMs and the same bus, would be slower than the card these were measured on; because that run's CUDA build is unrecorded, they are not a strict ceiling for this card either, and this page does not scale them. Searched for timings on this card and its AD104 siblings on 2026-09-23: the ComfyUI tracker's 21 Qwen-Image-2.1 threads (every comment), every discussion on the vendor's and Comfy-Org's Hugging Face repos and on the discussion tabs of the main third-party builds (Abiray, leejet, unsloth, toxicdog, realrebelai), the Hacker News launch thread, SGLang's Qwen-Image-2.1 cookbook (its rows are an RTX 4090, RTX 5090, RTX PRO 6000, DGX Spark, B200 and H200), unsloth's guide (which calls its memory figures estimates, not tested minimums), Civitai's 2.1 listings and a GitHub-wide issue search; Reddit refused this session. A timing of the template on an RTX 4070 is the most useful thing this page is missing: /contribute; it becomes the first datapoint on /check/qwen-image-2-1/rtx-4070.

  • VRAM usage: derived, not measured. The binding stage is the text encoder. Under DynamicVRAM, the default on this card: 8.709 GiB of weights plus comfy-aimdo's floor — on Windows 0.5 GiB, 9.209 GiB against 11.994 GiB, 2.785 GiB left; on Linux 0.25 GiB, 8.959 GiB against 11.586 GiB, 2.627 GiB left — before the desktop and the CUDA context, which the live check counts when it decides what to evict. Under the legacy loader (--disable-dynamic-vram and friends): 8.709 GiB plus ComfyUI's reserve — 10.095 GiB on Windows (1.899 GiB left), 9.899 GiB on Linux (1.687 GiB left). At 2048² the legacy decode partly unloads the DiT (at most 3.684 GiB of it stays on Windows), and under DynamicVRAM the sampler's activations are the unknown (0.895 GiB left on Windows if ComfyUI's doubled estimate were real). Neither Qwen nor Comfy-Org publishes a memory figure: the vendor's README gives enable_model_cpu_offload() as its only memory advice, and the docs page gives none.

  • Quality notes: (a) The VAE has a reported grid artifact. The vendor's discussion #12, titled "Diamond grid pattern caused by VAE", says "It's more noticeable when you generate a high-resolution image that has people with light skin tones and zoom in on their faces." (Rkss, community), and that a plain encode–decode round trip shows it. The mitigations named in the thread — a GLSL post-process node, a node pack, re-encoding through the Flux VAE — are workarounds, not fixes, and none is tied to a card; the thread was open on 2026-09-23 with no reply from Qwen. Inspect native-2K portraits at 100%. (b) On Comfy-Org's discussion #11 a user reported faint banding on skin, fabric and fur at the template's 25 steps, the same with either DiT, either encoder and either scheduler, and wrote "Artifact disappeared completely at 40" steps at 1024×1024. The same user wrote at 22:11 UTC that evening that with another user's workflow and a toned-down prompt they "see no streaks", and a third user advises 40 steps. So two remedies are reported, 40 steps and a less "high definition" prompt, by users and with no maintainer reply; nothing in the thread ties the banding to the VAE grid in (a) or to #16447.

For the full benchmark data, see /check/qwen-image-2-1/rtx-4070.

Troubleshooting

TextEncodeQwenImage21 or QwenImage21Cache missing when the template loads

Your ComfyUI core is older than v0.37.0. Take the v0.37.0 portable, or on a git install git fetch --tags && git checkout v0.37.0 && pip install -r requirements.txt, then check the version line at startup. The ComfyUI docs list not running the latest version as the first reason nodes go missing, and nodes that failed to import at startup as the second.

The startup log prints the cu130 WARNING

That is the quant_ops.py gate from step 2: your PyTorch was built against CUDA 12.x — on Windows, usually the cu126 portable. Everything still runs, the diffusion model on the eager INT8 path; reinstall PyTorch from the cu130 index (or take the nvidia portable) and confirm torch.version.cuda prints 13.0. No measurement of what it costs on an AD104 card turned up. On the one card where this site measured it, the operator's RTX 5060 Ti 16GB (a Blackwell card; one rig, one operator, unreplicated; cu128 session, cu130 session), the install whose log printed the warning took 69.4 s for the template's 1024×1024 image from a cold start, against 21.4 s on the cu130 portable. Those were two installs, not one flag flipped, and the figure is that card's, not this one's. kijai, a ComfyUI collaborator, replied on #16470, where a user on PyTorch 2.10.0+cu128 found the int8 file slower than a Q8_0 GGUF: "You need pytorch with cu130 for int8 models to work properly." A different line, Failed to import comfy_kitchen, is worse: the int8 formats these files use are defined by that package, so restore it with pip install -r requirements.txt before you debug anything else.

On Comfy-Org's discussion #13 a user asserts that int8 ConvRot is "significantly slower on non blackwell or enterprise GPUs", citing #16470 — a cu128 install — and naming no card and no timing of their own; another user replies that ComfyUI tested int8 as the best choice on old and new GPUs, without a link. Neither is a measurement on an Ada card; check the cu130 gate first.

JSONDecodeError: Expecting value: line 1 column 1 (char 0) when the text encoder loads

Issue #16472 reported this at the CLIPLoader with qwen3vl_8b_int8_convrot.safetensors; kijai replied "This is most likely a corrupt/incomplete model file.", the reporter wrote that a re-download fixed it, and the issue was closed as completed on 2026-09-22. Check the file's sha256 against step 3 and re-download before suspecting ComfyUI.

Edit output is speckled or ignores the instruction; text-to-image is clean

Issue #16435, under Editing. Set resolution to 1056. Disconnecting the VAE from TextEncodeQwenImage21 also removed the speckle in the first report, at the price of much weaker adherence to the reference.

Edits run many times slower than text-to-image

Most likely the K/V cache found no room and fell back to recomputing the prefix every step — on 12 GB the auto setting cannot pick the GPU while the DiT is resident (Editing). Set QwenImage21Cachedtype to int8 and device to cpu, shrink the references, or move to master for PR #16429, where #16443 reports a hard abort on image edits.

Fatal Python error: Aborted

Two open reports, both on the master code path:

  • At 0/25 when editing. Issue #16443, read in full on 2026-09-23 (four comments, the last on 2026-09-22 at 14:08 UTC). Two users, both with an RTX 5060 Ti 16 GB (the reporter with two of them, the second user with an extra RTX 3060 12 GB), say text-to-image works and describe the crash as intermittent and tied to larger input images: the second user saw it once the resolution went above 1 megapixel, the reporter with two inputs of about 1500×1000 but not so far after switching to smaller ones. The reporter added that forcing a single GPU did not help: "I also tested launching ComfyUI with --cuda-device 0 to force a single GPU, but the same crash still occurs." The stack ends in the prefix cache's take inside a malloc-graph recording that PR #16430 added on master; the v0.37.0 tag has no such recording around that call. PR #16450, open and reviewed only by a bot, proposes a fix.
  • On the second generation, during cleanup. PR #16481, opened 2026-09-22, reports on an RTX 5090 with PyTorch 2.13.0+cu130, the template's int8 files, dynamic VRAM and the cache node at auto that the first generation succeeds and the second aborts during sampler cleanup, with text-to-image and edit workflows alike; it proposes draining the device before unpinning the cache's host memory. The report says ComfyUI 0.37.0, but its stack's line numbers (qwen_image21/model.py line 238, model_base.py line 2678) are master's after the tag, where the tag has 236 and 2674. The cleanup code it patches exists at v0.37.0 too; no report of this crash on the tag turned up, which is not the same as the tag being immune. No maintainer has reviewed it.

No report of either names an AD104 card. If you hit the first on master, go back to v0.37.0 (git checkout v0.37.0, or update_comfyui_stable.bat on the portable) or feed smaller references; if you hit the second, restart ComfyUI and tell the PR's thread which build you were on.

Shape error [1, 338, 5120] from the text encoder

The CLIP loader was given something other than the 4096-wide Qwen3-VL-8B. The reporter of the repack's discussion #2 saw exactly this error while trying the w4a8 encoder, then closed the thread as having loaded the wrong encoder. Load qwen3vl_8b_int8_convrot.safetensors or qwen3vl_8b_w4a8.safetensors — not a qwen3.5_9b_…_pe_… file.

2K runs but the log says it retried the VAE decode tiled

That is the fallback working as designed; the 7.031 GiB decode estimate at 2048² is the largest working-set estimate on this page. The decode is slower and the image should be unchanged. What removes the tiling is more free VRAM — close what else is using the card (a browser with hardware acceleration counts), or render at 2 megapixels first. --vram-headroom 1 keeps an extra GiB free on the default loader, which trades DiT residency for decode room.

Every generation reloads models, or images turn green after a prompt change

Reloads are expected when the prompt or the resolution changes, for the co-residence reason in Requirements; a seed-only change should not reload. Those reloads are the trigger of an open defect: issue #16437, titled "Qwen-Image 2.1: --enable-dynamic-vram silently corrupts output after any model reload (channel slice offset, ROCm gfx1201)", reports that on an RX 9070 XT every image after the first reload comes back with its channels shuffled until the server is restarted, and that removing --enable-dynamic-vram fixed it. The reporter adds "I don't have an NVIDIA card to test whether this is ROCm-specific." No report of it on NVIDIA turned up in the ComfyUI tracker's 2.1 threads. If your images turn green after a prompt change, restart ComfyUI; if it keeps happening, start with --disable-dynamic-vram, which puts you on the legacy loader and its budget above.

GGUF: This model is not currently supported - (Unknown model architecture!)

Not the lead path here, since the int8 file is the template's own. But GGUF publishers disagree about loaders. city96's ComfyUI-GGUF, whose last commit is still 2026-01-12, passes a file whose general.architecture key is qwen_image straight to ComfyUI core; a file with no metadata key at all goes to a detection table that has no 2.1 entry. Read over HTTP range requests on 2026-09-23: Abiray's Q8_0 declares qwen_image (three metadata keys), while leejet's Q8_0 and unsloth's Q4_K_M declare none — the stable-diffusion.cpp convention. So Abiray's files should load on the stock loader once ComfyUI itself is v0.37.0 or newer — the publisher's answer to this error on its discussion #1 is to update both ComfyUI and ComfyUI-GGUF. leejet's files need leejet's fork, which adds the detection; on city96's repo, PR #483 proposes the same and was still open and unmerged on 2026-09-23. unsloth's files store their tensors under a model.diffusion_model. prefix that leejet's do not, so this page does not assume the fork takes them; on unsloth's discussion #5 a user who is not affiliated with unsloth posts this exact error and a community add-on as a stopgap, tested by that user with unsloth's Q4_K_M on an NVIDIA card. No GGUF run on an AD104 card turned up; if you make one, report it via /contribute.

See also: the 2025 20B predecessor has its own page for this card, on a GGUF Q3 path that the much smaller 2.1 no longer needs — Qwen-Image on RTX 4070. This is launch week and the tracker moves by the hour; report problems, or better a timed run on an RTX 4070, via the submission form.

common questions
How much VRAM does Qwen-Image-2.1 need?

About 12 GB — the minimum this recipe targets.

Which GPUs is Qwen-Image-2.1 tested on?

RTX 4070 (12 GB).

How hard is this setup?

Intermediate — follow the steps above.

next