self-hosted/ai
§01·recipe · image

Qwen-Image-2.1 on RTX 5070: int8 template in 12 GB, 2K, editing, and what native NVFP4 changes

imageintermediate12GB+ VRAMSep 23, 2026

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

models
tools
prerequisites
  • NVIDIA RTX 5070 12 GB (Blackwell GB205, compute capability 12.0)
  • 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
  • 32 GB system RAM recommended: the three template files are 16.096 GiB and whatever is not on the card lives in RAM
  • 18 GB 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 a 12 GB RTX 5070 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 (32 layers, per the repo's transformer/config.json) behind a Qwen3-VL-8B text encoder and a four-channel RGBA autoencoder with a 64-channel latent, released 2026-09-20. On this card the transformer is not the hard part — 6.758 GiB in int8. The text encoder is: at 8.709 GiB it is the larger file, and its stage comes closest to what the card reports.

This page was written on 2026-09-23 from public sources. The card is Blackwell, and that changes one thing against the other 12 GB pages in this series: it runs NVFP4 weights natively. Whether that is worth anything here is first a question of residency — speed on this card is unmeasured either way — and the answer is worked out under Running → Sub-int8 builds on this card.

⚠️ 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 and the community NVFP4 build included — is a derivative and carries the same terms. Section 2.b gives an address for a commercial licence; a reader reports in the vendor's discussion #7 that mail to it bounces. This is a reader's summary of the text, not legal advice.

Hardware data: RTX 5070 (12 GB VRAM, Blackwell GB205, compute capability 12.0) · not measured on this card by this site; every budget is derived · Windows reports the card as 12,227 MiB = 11.940 GiB, against 15.467 GiB for the template's encoder and diffusion model together, so they take turns · See benchmark data

ℹ️ Nothing on this page was measured on an RTX 5070 by this site, and no third-party run of this model on an RTX 5070 turned up in the sources searched (listed at the end of this page, read 2026-09-23). The site operator's two sessions for this model ran on a different card, an RTX 5060 Ti 16GB (cu130 session, cu128 session). This page uses them for two facts about the software and the files, never as a time or a memory figure for this card, and labels each use where it appears: (1) what the cu130 warning costs the int8 path (Troubleshooting, the cu130 entry); (2) that the w4a8 encoder gives a different composition from the same seed (Running, Sub-int8 builds). Each is one rig, one operator, unreplicated. Every VRAM figure below is arithmetic over byte counts and ComfyUI's own source at tag v0.37.0, shown so you can check it. If you run it, post your numbers.

The card. NVIDIA's RTX Blackwell architecture whitepaper (Appendix C, Table 6) lists the RTX 5070 as a GB205 with 12 GB of GDDR7 on a 192-bit bus and a PCI Express Gen 5 interface, and gives its peak FP4 tensor rate as 493.9 TFLOPS against 246.9 TOPS for INT8 (dense, at boost clock). NVIDIA's CUDA GPU list puts it at compute capability 12.0, the same entry as the RTX 5090. Those peak rates are why NVFP4 gets a section on this page; they are not a measurement of this model, and nothing below converts them into a time.

What the budgets need is the capacity CUDA reports, which is less than 12 GiB. ComfyUI prints it at startup as Total VRAM … MB (in MiB, rounded), and its system-stats block prints the exact bytes as VRAM Total. A search of the ComfyUI tracker returned nine distinct reports from a desktop RTX 5070 that carry either figure (bodies and comments read; three comments in #6833 quote one log). All nine are Windows (MSC-built Python, C:\/D:\ paths). Seven are startup logs, and all seven read Total VRAM 12227 MB (#6833, #9116, #9200, #10355, #11775, #12185, #14140); four carry a system-stats block, and all four give VRAM Total as exactly 12,820,480,000 B (#7444, #9200, #14140, #16015); #7444 and #16015 have only the block. That is 12,226.5625 MiB, and 12,820,480,000 B = 11.940 GiB is the figure every budget below uses. No Linux log from this card turned up (queries listed at the end of this page), so this page does not print a Linux capacity; on the RTX 5070 Ti the Linux logs read lower than the Windows ones, so do not assume the Windows figure on Linux — read yours from the startup log. One more reading is worth knowing, with its limits. Two of those Windows reports, both on a cu130 portable (#14140 and #16015, months apart), show VRAM Free = 11,571,036,160 B, byte-identical, with Torch VRAM Total: 0. Each block was captured when its error report was written, after work had already run in that session (#14140's after a model load and a traceback), not right after startup. So 1,249,443,840 B = 1.164 GiB of the card was not free at that moment, and the blocks do not say what held it. This page uses it only as an example size for the share the desktop, the CUDA context and other software can take — the share every "spare" figure below still has to cover — and labels it "the two error-report readings" wherever it appears.

Requirements

ComponentMinimumThis recipe
GPU12 GB VRAM, NVIDIARTX 5070 (12 GB) — not measured by this site; the budget below is derived (/contribute)
RAM32 GB recommended— the three files are 16.096 GiB, and what is not on the card lives in RAM
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 three files the official templates load, byte-exact from the Comfy-Org repack at revision ace0edeb. The repo's head moved to 5dc5850e on 2026-09-22 with a README-only change; every weight file has the same size and LFS sha256 at both revisions (tree API, read 2026-09-23).

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 — past 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) and two qwen3.5_9b_…_pe_… files, which are prompt enhancers, not encoders. Its recursive tree lists exactly two diffusion-model files, bf16 and int8: there is no Comfy-Org fp8 or nvfp4 DiT for 2.1 in it. The ComfyUI docs page was synced with the templates on 2026-09-22 (source at 9d133794) and now lists the two int8 files as the ones the templates load, with the bf16 files as the full-precision alternatives, so the docs and the templates agree.

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 loaders — the definition this model's RTX 3060 page uses. On this card's reported 11.940 GiB it holds: the largest stage, the encode, asks for 10.095 GiB on the Windows legacy loader (below).

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 NVIDIA once PyTorch is 2.8 or newer and comfy-aimdo initialises, and the log says DynamicVRAM support detected and enabled. You land on the legacy estimate-based loader if you pass --disable-dynamic-vram (or --highvram, --gpu-only, --novram, --cpu), or if the 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/sd.py, comfy/model_patcher.py), from comfy-aimdo v0.5.5 (the version requirements.txt pins), and from the byte counts above. All sums are over unrounded bytes, rounded once.

DynamicVRAM (the default). ComfyUI's own reserve and its memory estimates do not decide residency here. ModelPatcherDynamic.partially_load() accepts the extra_memory argument load_models_gpu() passes and never uses it, and the comment on memory_required() says that with every model dynamic the estimate "is ignored and its all done dynamically." The floor is comfy-aimdo's, and it differs by OS. On Windows the aimdo DLL is built with the Windows sources (build workflow), and src-win/shmem-detect.c keeps 512 MiB free against both the WDDM budget and NVML's free-VRAM reading (96 MiB if it has to fall back to cuMemGetInfo). On Linux, src/plat.h defines VRAM_HEADROOM (256 * 1024 * 1024) and src/control.c keeps that much free against live free VRAM. Both are live checks, so the desktop's share and the CUDA context are counted when aimdo decides what to evict. Weights load on demand and are 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". A stage never fails for want of room for its weights; what the numbers tell you is whether they can stay resident for the whole stage. Activations are real allocations on top, which no loader estimates on this path.

Stage (DynamicVRAM, Windows)Weights+ aimdo floorStage totalAgainst the 11.940 GiB Windows reports
Text encode, int8 encoder8.709 GiB0.500 GiB9.209 GiB2.731 GiB spare
Text encode, w4a8 encoder5.879 GiB0.500 GiB6.379 GiB5.561 GiB spare
Sampling, int8 DiT (weights only)6.758 GiB0.500 GiB7.258 GiB4.682 GiB spare, for activations too
VAE decode (weights only)0.629 GiB0.500 GiB1.129 GiB10.811 GiB spare, for the decode's own allocations

On Linux every total is 0.250 GiB lower (the encode stage is 8.959 GiB), against a Linux capacity this page could not read from any log. The spare column is against the capacity, so the desktop and the CUDA context still come out of it: against the free figure of the two error-report readings (above), the int8 encode stage leaves 11,571,036,160 − 9,887,669,272 = 1,683,366,888 B = 1.568 GiB.

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 sets to 400 MiB on Linux and 600 MiB on Windows, adding 100 MiB more on Windows only when the card's total exceeds 15 × 1024 MiB — not this card, at 12,227 MiB. So the fixed floor is 1.191 GiB on Linux and 1.386 GiB on Windows. For sampling, two estimates are involved, both from the activation formula area × 2 bytes × 0.01 × 6.0 MiB (memory_usage_factor 6.0 for this model in supported_models.py; its source comment says the formula needs tweaking). sampler_helpers.py computes the estimate at double batch — noise_shape[0] * 2, whatever the cfg — which is 0.960 GiB at 1024² (latent 64×64) and 3.840 GiB at 2048² (128×128), and a separate minimum at batch 1, 0.480 and 1.920 GiB. Before loading, the loader tries to free 1.1 × the weights plus the larger of the fixed floor and the estimate plus EXTRA_RESERVED_VRAM, unloading other models to get there; it then loads the model whole only if free VRAM covers the weights plus the larger of the fixed floor and the minimum plus EXTRA_RESERVED_VRAM, and partially otherwise. The VAE decode passes its own estimate, 900 × h × w × 256 × 2 bytes over the latent grid for this VAE (sd.py): 1.758 GiB at 1024², 7.031 GiB at 2048². The residency thresholds:

Stage (legacy loader)WeightsKept free, WindowsThreshold, Windowsvs 11.940 GiBThreshold, Linux
Text encode, int8 encoder8.709 GiB1.386 GiB (fixed floor; the encoder passes no estimate)10.095 GiB1.845 GiB spare9.899 GiB
Text encode, w4a8 encoder5.879 GiB1.386 GiB7.265 GiB4.675 GiB spare7.069 GiB
Sampling at 1024²6.758 GiB1.386 GiB (0.480 + 0.586 is below the floor)8.144 GiB3.796 GiB spare7.949 GiB
Sampling at 2048²6.758 GiB2.506 GiB (1.920 + 0.586)9.264 GiB2.676 GiB spare9.069 GiB
VAE decode at 1024²0.629 GiB2.344 GiB (1.758 + 0.586)2.973 GiB8.967 GiB spare2.778 GiB
VAE decode at 2048²0.629 GiB7.617 GiB (7.031 + 0.586)8.246 GiB3.694 GiB spare — only with the DiT off the card8.051 GiB

What the loader tries to free before sampling is larger: on Windows 8.980 GiB at 1024² (1.1 × 6.758 + 0.960 + 0.586) and 11.860 GiB at 2048², which is more than this card can have free once anything else holds VRAM — so at 2K the legacy loader unloads every other model it can (the encoder, the VAE) before it samples. Against the free figure of the two error-report readings, the int8 encode stage's 10.095 GiB leaves 11,571,036,160 − 10,838,937,419 = 732,098,741 B = 0.682 GiB.

Four things follow.

The encoder and the DiT never sit on the card whole at the same time. The two files the stages alternate between are 6.758 + 8.709 = 15.467 GiB, past the 11.940 GiB the card reports before any floor. Under DynamicVRAM ComfyUI does not unload one model to make room for the other — the comment in free_memory() says "don't actually unload dynamic models for the sake of other dynamic models" — and aimdo evicts weights as allocations need the room. The consequence is an inference from the arithmetic and from aimdo's design, not a measurement. Eviction is per weight: the aimdo README says "The most recent VBARs are the highest priority", and ComfyUI moves each dynamic model to the top when it loads it (vbar.prioritize() in model_patcher.py), so encoding pushes out DiT weights and sampling pushes out encoder weights, as far as each needs. The two can keep at most 11.940 − 0.500 = 11.440 GiB between them on Windows, so a new prompt has to bring back at least 16,607,581,424 − 12,283,609,088 = 4,323,972,336 B = 4.027 GiB of the encoder and then as much of the DiT — more once the CUDA context, the display and activations take their share (5.191 GiB of each at the two error-report readings' share). A seed-only change reuses the cached conditioning and skips the encode. Unlike on a 16 GB card, the w4a8 encoder does not change this here: w4a8 plus the int8 DiT is 13,568,888,428 B = 12.637 GiB, which is 748,408,428 B = 0.697 GiB more than the card reports. On this card it buys room in the encode stage, not co-residency.

The encoder stage is the binding one in both views: 9.209 GiB under DynamicVRAM and 10.095 GiB legacy on Windows (8.959 and 9.899 GiB on Linux). Neither loader budgets for 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 — and with the share of the two error-report readings taken, the legacy loader has 0.682 GiB for it on Windows.

At 2K the decode is what is tight, and only the legacy loader reserves for it. On the legacy loader the 2048² decode threshold is 8.246 GiB on Windows, and with the int8 DiT still resident the request would be 6.758 + 0.629 + 7.031 + 0.586 = 15.005 GiB, so the DiT is moved off the card (partly or whole) before the decode. On the default loader the VAE is a dynamic model too — sd.py builds it with CoreModelPatcher, which main.py rebinds to ModelPatcherDynamic when DynamicVRAM is on — so nothing unloads the DiT for it, and VAE.decode() uses the estimate only to pick how many images to decode per pass, which for one image is one. Whether a 2K decode on this card pushes DiT weights off is decided by the decode's real allocations under aimdo's floor, and no such measurement turned up in the sources searched. On a real out-of-memory either loader logs "Warning: Ran out of memory when regular VAE decoding, retrying with tiled VAE decoding." and finishes tiled.

Sampling itself is not the problem at 2K on the default loader. The int8 DiT's 7.258 GiB with the Windows floor leaves 4.682 GiB of the card for activations; the largest single tensor in a block, the fused MLP gate_up output (24,576 wide, read from the NVFP4 build's tensor shapes below), is 805,306,368 B = 0.750 GiB at 16,384 image tokens. One tensor is not a peak, and no peak has been published.

Installation

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

Support landed in ComfyUI core with PR #16400 (author kijai, merged 2026-09-19), and tag v0.37.0 (commit 73c9bad4) contains it. The v0.37.0 release, with its Windows portable builds, was published at 07:35 UTC on 2026-09-21 and was still the latest GitHub release at 06:06 UTC on 2026-09-23. A v0.37.1 tag was cut at 19:12 UTC on 2026-09-22 (commit 3f767e7f67), with no release object or portable behind it as of that check; against v0.37.0 it adds three commits — Hunyuan Image 3.5 partner nodes (#16462), the workflow-templates pin raised from 0.11.66 to 0.11.68 (#16466), and the version bump. None of the three changes this model's code or any of the three Qwen-Image-2.1 workflow files, which are unchanged since 371a7b7171, the commit templates 0.11.66 already carried; what templates 0.11.67–0.11.68 add for 2.1, beside the new Hunyuan templates, is translated titles and descriptions for its background-removal template and a trailing comma in bundles.json. The backport PR #16467 was closed without merging. This page keeps v0.37.0 as its floor.

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." 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). 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          # the floor and the safer default; see "Tag or master?" below
python3 -m venv .venv && source .venv/bin/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())"
# expect a +cu130 build, 13.0, and (12, 0)

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 R580 branch or newer, per NVIDIA's CUDA release notes. ComfyUI's maintainer put the support position plainly on #16455: "We do not support using cuda 12 on newer GPUs." requirements.txt at the tag pins comfy-kitchen==0.2.35, comfy-aimdo==0.5.5 and comfyui-workflow-templates==0.11.66; that comfy-kitchen release builds its wheels with 120f in the CUDA architecture list on Windows and Linux (setup.py), which covers compute capability 12.0. Leave this shell open with .venv active: step 3 runs in it.

Tag or master? master was v0.37.0 plus 15 commits at 03:16 UTC on 2026-09-23. Three of them change the 2.1 transformer file, comfy/ldm/qwen_image21/model.py: PR #16429, which changes where the edit path's K/V cache is placed, PR #16430, which compiles the 2.1 transformer blocks, and PR #16419, which lets a model file choose the attention used per block. A fourth, PR #16442, adds a system-prompt argument to the Qwen3-VL tokenizer for TextGenerate, and PR #16425 extends fast-disk detection to all model loaders. None is needed to run the templates, and both open crash reports for this model on NVIDIA come from post-tag builds. One is #16443, a hard abort on image editing (Troubleshooting). The other is in open PR #16481, whose author reports on an RTX 5090 — the same compute capability as this card — with the template's int8 files, cu130, DynamicVRAM on and QwenImage21Cache at auto, that the first generation succeeds and the second aborts during sampler cleanup, in text-to-image and in edits. That report's log says ComfyUI 0.37.0, but its stack's line numbers match master at commit b33e2b55 (qwen_image21/model.py line 238, model_base.py line 2678, model_patcher.py line 1318) and not the v0.37.0 tag, where those lines are other code (master's version file still reads 0.37.0, so the banner cannot tell them apart). The cleanup path it aborts in — reset_prefix_cache() freeing the prefix cache's pinned host memory — is in the tag too, at lines 234–238 of the same file, and no report from the tag turned up in the tracker threads read; the PR has had no maintainer review. The tag is the safer default, not a proven-immune one. If a second generation ever aborts on the tag, that PR is the place to report it.

2. What compute capability 12.0 gets from these files

Both int8 files carry, per layer, the format int8_tensorwise with convrot: true and a group size of 256 (read from each file's safetensors header). What happens to them 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 a quantised model as a line starting Native ops:. On compute capability 12.0 every check in model_management.py passes: supports_int8_compute() has no compute-capability test at all, supports_fp8_compute() is true from major 9, supports_nvfp4_compute() from major 10, and supports_mxfp8_compute() from major 10 with PyTorch 2.10 or newer. So at v0.37.0 the line should list all seven formats (int8_tensorwise, convrot_w4a4, asym_w4a8_int8, nvfp4, mxfp8, float8_e4m3fn, float8_e5m2, in no fixed order) with no emulated ops part. The one RTX 5070 log found that prints the line is older — #14140, ComfyUI 0.25.0 on a Windows portable with PyTorch 2.12.0+cu130, before the int8 formats existed — and it reads Native ops: float8_e5m2, mxfp8, nvfp4, float8_e4m3fn with no emulated part: every format that release knew, native on this card.

Which kernel then serves a native layer is decided one level down, in comfy-kitchen's CUDA backend (backends/cuda/__init__.py, pinned at the commit tagged v0.2.35). Three formats matter on this page, and the card treats them differently:

  • int8 (the template's DiT): the CUTLASS INT8 path is enabled for compute-capability major 8 and above, so on this card the activations are rotated and quantised in a fused kernel and the GEMM runs as INT8.
  • nvfp4: scaled_mm_nvfp4 is registered with min_compute_capability=(10, 0), so it is available here — a cuBLAS FP4 GEMM, native on this card and emulated on the Ampere and Ada 12 GB cards in this series.
  • convrot_w4a4 (the INT4 ConvRot builds): _cuda_device_supports_native_int4_mma() ends in return major == 8. Its comment calls the kernel's MMA the "sm80+ integer MMA shape" and says Hopper is sent to the INT8 fallback for better behaviour with that implementation. The test admits major 8 only, so compute capability 12.0 takes the fallback too; the comment gives a reason for Hopper alone, and no source here shows whether sm_120 could run that MMA natively (the Blackwell whitepaper lists FP4 and INT8 tensor rates and no INT4 rate). On this card convrot_w4a4_linear therefore takes its fallback: the activations are quantised to int8, not int4, and multiplied against the 4-bit weights through an int8-activation GEMM — effectively W4A8, which keeps more activation precision than the W4A4 in the name. It runs; it is not the 4-bit kernel the build is named for, and its speed here is unmeasured.

For the text encoder none of that applies. 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 switch back to quantised matmuls wraps LLM text generation, not the conditioning encode this model uses. The encoder's file format is a memory choice, not a speed choice, here as on any card.

Without cu130 nothing breaks; the DiT 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 its backend order (cuda, triton — off by default — then eager), and the eager int8_linear applies the rotation as ordinary torch ops and still multiplies in INT8, without the fusion. The Native ops line will not warn you: it reflects the hardware, not which backend is alive. The tells are that WARNING and the startup line Found comfy_kitchen backend cuda: showing 'disabled': True — the RTX 5070 log in #12185 (ComfyUI 0.11.1, PyTorch 2.10.0+cu130) shows the healthy form, 'available': True, 'disabled': False.

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. On a git install, run this from the ComfyUI folder with .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 ace0edeb3791a594ddfa36ed5f41a178a394e921 --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:

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 ace0edeb3791a594ddfa36ed5f41a178a394e921 --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 before you debug anything (on Windows, certutil -hashfile <file> SHA256 prints the same hash):

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

About the encoder. Comfy-Org's qwen3vl_8b_bf16.safetensors carries the same LFS sha256 (68bdc82b…) in the 2.1 repack and in Comfy-Org/Qwen3-VL, a repository that predates this model, and on the vendor's discussion #5 two readers report comparing tensors against stock Qwen3-VL-8B-Instruct and finding no retraining; Qwen has not said so itself. ComfyUI picks the 2.1 encoder class from tensor names (the vision tower's DeepStack merger) plus type: qwen_image, not from the file name, so any complete 8B Qwen3-VL build in a format it loads takes the same route. Comfy-Org/Qwen3-VL also holds an fp8_scaled 8B file (10,588,637,512 B = 9.861 GiB) and an nvfp4 one (6,305,221,764 B = 5.872 GiB). No report of either Comfy-Org file being used with 2.1 turned up in the discussions searched (the one nvfp4 hit in them is about Krea 2), and there is no reason to reach for them on this card: the fp8 file is larger than the int8 one, the nvfp4 file is 6,883,600 B smaller than the w4a8 encoder, and both are dequantised for the encode anyway.

Running

Start ComfyUI normally — no --lowvram, no --reserve-vram:

python main.py

On the portable, run run_nvidia_gpu.bat. Read the first screen of the log: ComfyUI version: 0.37.0 or higher; pytorch version: ending in +cu130 with no cu130 WARNING; Found comfy_kitchen backend cuda: with 'disabled': False; Total VRAM 12227 MB on Windows; DynamicVRAM support detected and enabled. --lowvram is documented in comfy/cli_args.py as "Doesn't do anything if dynamic vram is enabled." — adding it out of 12 GB habit changes nothing. You need no flag for the desktop: aimdo's live check already counts it. If you want more kept free anyway, --vram-headroom N adds N GiB on top of both of aimdo's checks; --reserve-vram N only raises the check against the card's total capacity (aimdo's control.py documents that lowering it below 256 MB changes nothing), and it is also what replaces EXTRA_RESERVED_VRAM on the legacy loader.

Text-to-image

Open the Template Library and load Qwen Image 2.1: Text to Image (image_qwen_image_2_1_t2i.json, templates 0.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 template's note on the setting people change first: "negative_prompt: unused while cfg is 1.", and on cfg: "cfg: keep 1 for the Qwen Image 2.1 official path. Raise it only if you use a negative prompt." Raising cfg adds a second model pass on every step. For native 2K the note says "For native 2K, set 1:1 and 4 megapixels".

On steps: the vendor's diffusers example runs 40, the template 25. One user on the repack's discussion #11 reports faint banding on skin, fabric and fur at the template's 25 steps, with the int8 and the bf16 files and with both schedulers, and writes "Artifact disappeared completely at 40" steps at 1024×1024. The same user wrote later that evening that with another user's workflow and a toned-down prompt they "see no streaks", and a third user in the thread advises 40 steps. So two remedies are reported, from a handful of users and no maintainer: 40 steps, or a different workflow with a less "high definition" prompt. Neither was tested for this page.

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. A community GGUF conversion of that transformer, realrebelai/Viggle_Qwen-Image-2.1-Turbo_GGUFs, added six files from Q2_K to Q8_0 late on 2026-09-22; its Q4_K_M header declares general.architecture = qwen_image. It was not run for this page either.

For a transparent image, wrap the prompt the way the model card does — This is an RGBA image with transparency. <your subject>. The image has alpha channel and the background is transparent. — and keep the template's SaveImageAdvanced at PNG, which keeps the alpha channel.

Expect the first run to encode, sample, then decode; a prompt change to repeat the encode and move weights back and forth (What actually gates this card); a seed-only change to skip the encode. At 2K the sampling schedule does not follow the resolution: ComfyUI fixes this model's shift at 0.69, the value its source comment gives for 1024×1024, and open #16447 reports that the vendor's pipeline shifts dynamically instead; a ComfyUI maintainer replied that the fixed value is partly deliberate.

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 TextEncodeQwenImage21 with the VAE connected — each reference is seen by the encoder's vision tower and spliced into the sequence as latents — and resolution at 0 on its outer node, whose note says "This template starts at 0: no resize beyond a multiple of 32." A QwenImage21Cache node sits at device auto, dtype default.

Set resolution to 1056 before you edit. Open #16435 reports broken edits (over-sharpened speckle, or the instruction ignored) at particular reference grids, and its two reports disagree on which: 1024×1024 broken on Apple MPS and CPU, while on an RTX 5070 Ti (v0.37.0 tag, cu130, the bf16 DiT with the int8 encoder) 1024×1024 was clean and 1536×1024 broke, at resolution 0 and at 1248. resolution 512 and 1056 were clean in both reports, and 512 shrinks the references to a quarter megapixel, so use 1056; it resizes the output canvas to about 1056×1056 pixels in the first reference's aspect ratio. Disconnecting the VAE from the node also removed it in both, at the cost of much weaker reference adherence. The two setups differ in backend, OS, build, attention path, encoder precision, reference image and step count, so neither isolates a cause; neither report, and none in the sources searched, comes from an RTX 5070. The issue was open on 2026-09-23. PR #16444, a proposed fix, was closed without merging on 2026-09-22 by kijai; no fix is linked to #16435 now.

On a 12 GB card, where the edit cache lands decides the speed. comfy/ldm/qwen_image21/model.py sizes the text-and-reference prefix cache at 2 × 32 layers × tokens × 4096 × 2 bytes — 524,288 B per token. The template's two 896×1152 references at resolution 1056 resize to 928×1184, 2 × 58 × 74 = 8,584 tokens: 4,500,488,192 B = 4.191 GiB in bf16, before the prompt's own tokens. The node's dtype divides that by 2 (int8) or 4 (int4): 2.096 or 1.048 GiB. At v0.37.0, select_prefix_cache() in auto places the cache on the GPU only if four times its size is free there, else in system RAM under the same four-times rule, and otherwise recomputes the prefix on every step. With the int8 DiT on the card, at most 12,820,480,000 − 7,256,783,064 = 5,563,696,936 B = 5.182 GiB can be free, so the bf16 (16.766 GiB) and int8 (8.383 GiB) caches cannot take the GPU; an int4 cache (4.191 GiB for four times) could only if everything else on the card held less than 1,063,208,744 B = 0.990 GiB at that moment, which a share like the 1.164 GiB of the two error-report readings would not meet. So the RAM leg decides: four times the cache free in system RAM, while that RAM also holds the staged weights. Setting device to cpu skips the four-times check (the source still wants twice the cache size free in RAM). The node's own tooltips in comfy_extras/nodes_qwen.py on the trade: int8 "halves the cache at about bf16 accuracy", and int4 "quarters it but roughly doubles the per-step error." On the tag, dtype int8 is the first thing to try when edits are slow. PR #16429's author timed the difference this placement logic makes on an RTX 5080, a 16 GB card; those are that card's numbers and are not repeated here.

Sub-int8 builds on this card: what the arithmetic says

Of the six 12 GB cards in this catalogue (RTX 3060, 3080 Ti, 4070, 4070 Super, 4070 Ti, 5070), this is the only one that runs NVFP4 natively, so this question is specific to this page. The template runs here without any of these builds: every stage keeps its weights whole on its own. What a smaller build could change is how much has to move back onto the card after a prompt change — at least 4.027 GiB of each model with the template (What actually gates this card). The options, by file bytes (tree API, 2026-09-23), on Windows:

Encoder + DiT on the cardWeightsLeft at sampling (after the 0.500 GiB aimdo floor)Left at decode (also after the 0.629 GiB VAE)Same two, at the two error-report readings' share
int8 + int8 (the template)15.467 GiBover by 3.527 GiB before any floor
w4a8 + int812.637 GiBover by 0.697 GiB before any floor
int8 + NVFP412.618 GiBover by 0.678 GiB before any floor
w4a8 + NVFP49.788 GiB1.652 GiB1.023 GiB0.488 GiB / over by 0.141 GiB
w4a8 + INT4 ConvRot9.293 GiB2.147 GiB1.518 GiB0.983 GiB / 0.354 GiB

"Left" is against the 11.940 GiB the card reports, so the CUDA context and the display still come out of it, and so do the stage's own allocations. At sampling those are the activations: at 1024² the largest single tensor in a block, the MLP's gate_up output, is 201,326,592 B = 0.188 GiB, and at 2048² 0.750 GiB. At decode they are the VAE's working memory, which the default loader does not estimate; the legacy loader's planning figure for it at 1024² is 1.758 GiB, more than the 1.023 GiB left beside the NVFP4 pair. With the NVFP4 pair and the VAE on the card, the three files and the floor come to 11,722,060,628 B = 10.917 GiB, which is already 151,024,468 B = 0.141 GiB more than the free figure of the two error-report readings before the decode allocates anything.

So whenever the context, the display and the decode's real allocations together exceed 1.023 GiB — as they already do at that share, and as the legacy planning figure alone would — the decode evicts something, and the source says what. ComfyUI moves each dynamic model to the top of aimdo's priority when it loads it (vbar.prioritize() in model_patcher.py), and the aimdo README gives the most recently prioritised model the highest priority; after encode, sample and decode, the encoder is the lowest, so its weights are the first to go. At 1024² a prompt change on the NVFP4 pair then still re-stages part of the encoder — as much as the context, the display and the decode's real allocations took beyond the 1.023 GiB, which with a decode near the legacy figure is 789,017,428 B = 0.735 GiB (1.898 GiB at the error-report share) — instead of at least 4.027 GiB of each model. At 2048² a decode near the legacy 7.031 GiB figure leaves 6,451,327,828 B = 6.008 GiB of excess (7.172 GiB at that share), more than the whole 5.879 GiB encoder, so the next prompt re-stages all of the encoder and at least 0.130 GiB (1.293 GiB at that share) of the DiT — still less than the template's 8.709 GiB of encoder plus at least 4.027 GiB of DiT. That is an inference from the arithmetic and the code; neither reload has been measured on this card in the sources searched. On the legacy loader the pair does not hold even at sampling in practice: before sampling it tries to free 1.1 × 3.909 + 0.960 + 0.586 = 5.846 GiB on Windows, and with the w4a8 encoder's 5.879 GiB on the card only 6.061 GiB is free before the desktop and context, so the encoder stays only if they hold less than 231,104,755 B = 0.215 GiB.

This page's decision: document the NVFP4 DiT + w4a8 encoder pair as an optional swap with its trade-off stated, not as the install. The reasons, each labelled:

  • What it buys (inference, unmeasured): a smaller reload after a prompt change, as above, and possibly faster sampling, since this card's FP4 tensor peak is twice its INT8 peak (The card) — but no run of an NVFP4 DiT on any 12 GB card, or on the v0.37.0 tag, turned up in the sources searched, so neither gain has a number. Its converter's own runs were on an RTX 5090 with a pre-release build, and the publisher's PR #16432 reports stock master (commit c194dd00, four commits past the tag) running the files on the same RTX 5090; those timings are a 32 GB card's, where everything stays resident either way, so they are not repeated here. The tag has the nvfp4 format and the 2.1 model code, so it should load; that is a reading of the code. On a seed-only change the saving depends on the resolution: the encode is skipped in either setup, and at 1024² a decode near the legacy figure fits beside either DiT, so there is no reload to save. At 2048² a decode near the 7.031 GiB legacy figure pushes DiT weights off the card, and the next seed re-stages about 3,198,430,864 B = 2.979 GiB of the int8 DiT on the template against 139,222,464 B = 0.130 GiB of the NVFP4 one (4.142 against 1.293 GiB at the error-report share) — inference, since the default loader's real 2K decode is unmeasured. Any difference in sampling speed is unmeasured at either size.
  • What it costs (sourced): the DiT becomes a third party's 4-bit requantisation of the model that draws the image. BennyDaBall/Qwen-Image-2.1-NVFP4's file is 4,197,574,664 B = 3.909 GiB; its header marks all 192 quantised matrices (six per block × 32 blocks) nvfp4 and keeps the embedding, modulation, normalisation and output tensors in bf16. Its converter's validation notes publish 24 same-seed pairs against bf16 and list real differences (changed portrait details, object placement, typography layout), and state "Hardware other than the RTX 5090 was not benchmarked." The w4a8 encoder, Comfy-Org's own file, changes the picture too: on the operator's RTX 5060 Ti it gave a clearly different composition from the same seed, just as clean (one rig, one operator, unreplicated; cu128 session). If neither a smaller reload nor an unmeasured speed difference matters to you, the template is the better choice.
  • Why this NVFP4 build (sourced): several NVFP4 and 4-bit DiT repos exist on the Hub (among them pottokao's, ModelsLab's, HangGlidersRule's and Rin247's). This page names BennyDaBall's because three things about it are published and checkable: its conversion source (the Comfy-Org bf16 file at the revision this page pins, per its README), a per-layer format readable from its header, and the 24-pair comparison above. This page did not evaluate the others.
  • Why this pair on 12 GB (arithmetic): on a 16 GB card the w4a8 encoder alone keeps both models on the card, which is why the 16 GB Blackwell pages in this series stop there; on 12 GB it falls 0.697 GiB short. Of the three pairs in the table with a 4-bit DiT, only the two that pair it with the w4a8 encoder fit; on the Ampere and Ada 12 GB pages NVFP4 is emulated, while here scaled_mm_nvfp4 serves it (Installation, step 2).
  • Why not INT4 ConvRot, although it leaves more room (source + one report): toxicdog/Qwen-Image-2.1-INT4ConvRot-ComfyUI's DiT (3,666,512,184 B = 3.415 GiB, all 193 layers convrot_w4a4 in its header) fits with 0.495 GiB more than the NVFP4 pair. On this card it runs through comfy-kitchen's int8-activation fallback (Installation, step 2), so its speed here is unknown, and its output should if anything sit closer to a W4A8 build than its name suggests — an inference from the code path. No same-seed comparison of it was found; the one quality report on it among the sources searched, the repo's discussion #1, calls INT4 output poor without naming a GPU or saying whether it used that repo's INT4 DiT or its INT4 encoder. If room matters more to you than a published comparison, it is the one with room.
  • Why not an NVFP4 encoder (source): the encode dequantises every format (Installation, step 2), Comfy-Org's nvfp4 8B file saves 6,883,600 B against w4a8, and BennyDaBall's own NVFP4 encoder is 7,549,882,768 B = 7.031 GiB, larger than w4a8, and needs its GPL runtime patch to run the encode in FP4 at all.

If you want the pair, download the one extra DiT and the w4a8 encoder (same folders as step 3), check both, then set unet_name and clip_name on the template's outer node:

hf download BennyDaBall/Qwen-Image-2.1-NVFP4 diffusion_models/qwen_image_2.1_nvfp4.safetensors \
  --revision 1a38d44a3a2f35cb0b543a25b04da0a963e7b5e6 --local-dir models
hf download Comfy-Org/Qwen-Image-2.1 text_encoders/qwen3vl_8b_w4a8.safetensors \
  --revision ace0edeb3791a594ddfa36ed5f41a178a394e921 --local-dir models
sha256sum models/diffusion_models/qwen_image_2.1_nvfp4.safetensors
# 4fdbaec94c19f7b8888f1e1ddbae05354c014492f9b2547b1cd8dca0ce923526
sha256sum models/text_encoders/qwen3vl_8b_w4a8.safetensors
# 7754425e55e7bea2bfde4dde59a4cc236cb44e5ee9c215ea66ef8d47012824eb

(On the portable, prefix each hf download with python_embeded\python.exe -s -m huggingface_hub.cli.hf, use --local-dir ComfyUI\models, and check with certutil -hashfile <file> SHA256, as in step 3.) The Native ops line should list nvfp4 as native when the DiT loads. If you try it, the useful report is a time per image after a seed change and after a prompt change, with the template's for comparison — the … MB Staged log lines print a model's full size, not how much was re-read, so they cannot answer it: /contribute.

GGUF, for completeness. The diffusion-model GGUFs dequantise each weight before the matmul, so on this card they give up the INT8 or FP4 GEMM, and a Q8_0 saves nothing against the int8 file. Abiray/Qwen-Image-2.1-GGUF's files declare general.architecture = qwen_image, which city96's loader.py (head unchanged since 2026-01-12) hands to ComfyUI core; leejet/Qwen-Image-2.1-GGUF's carry no metadata keys and need leejet's fork; a pull request adding detection for those to city96's node, #483, is open. A GGUF of the text encoder is a different matter: stock city96 loads the vision projector only for qwen2vl, so a Qwen3-VL GGUF without it is built as the wrong encoder class; #485, opened 2026-09-23 to fix that, is unmerged. None of these has a published run on an RTX 5070 in the sources searched.

Results

  • Speed: omitted. No timing on an RTX 5070 turned up in the sources searched (listed at the end of this page), and GB205 has no other 12 GB card in this catalogue whose figure could stand in for it. The named-card timings that exist are on larger cards — an RTX 4090 in the Hacker News launch thread, an RTX 5080 in PR #16429, RTX 5090s in PR #16430, PR #16432 and PR #16481 — where more stays resident, so none of them is a figure for this card. If you time a run — steps, resolution, seconds per image, whether the decode fell back to tiled — post it; it becomes the first datapoint on /check/qwen-image-2-1/rtx-5070.
  • VRAM usage: derived, not measured. The binding stage is the text encoder. Under DynamicVRAM, the default: 8.709 GiB of weights plus aimdo's floor — on Windows 0.500 GiB, 9.209 GiB against the 11.940 GiB the card reports, 2.731 GiB spare, 1.568 GiB at the two error-report readings' share; on Linux 0.250 GiB, 8.959 GiB against a capacity no log gave. Under the legacy loader: 10.095 GiB on Windows (1.845 GiB spare; 0.682 GiB at that share) and 9.899 GiB on Linux. The legacy 2K decode threshold is 8.246 GiB on Windows (8.051 GiB on Linux) with the DiT off the card; the default loader reserves nothing for the decode. No measured peak at native 2K on a 12 GB card was found. The vendor publishes no VRAM figure: its card and README give enable_model_cpu_offload() as their memory advice. The one 12 GB mention in the discussions searched is a comment on the vendor's discussion #13 saying a Q8 DiT with a Q6 encoder stays below 12 GB of VRAM, naming no card, runtime or resolution.
  • Quality notes: 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, crediting the example image to another user), with an encode–decode round trip given as the way to see it; a third commenter argues that a similar stripe pattern in a different model came from the DiT, so the attribution is a community reading, not the vendor's. The mitigations named there (a GLSL post-process node, a node pack, re-encoding through the Flux VAE) are workarounds, and none is tied to a card. The 25-step banding report is under Text-to-image; nothing ties it to the VAE grid. Inspect native-2K portraits at 100%.

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

Troubleshooting

TextEncodeQwenImage21 or QwenImage21Cache missing when the template loads

You are below v0.37.0. Update to the v0.37.0 portable, or on a git install git fetch --tags && git checkout v0.37.0 && pip install -r requirements.txt (a bare git pull lands on master), then check the version line. The ComfyUI docs page lists 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

Your PyTorch is a CUDA 12 build — on Windows, usually the cu126 portable or an older Desktop install. Everything still runs, the DiT on comfy-kitchen's eager INT8 path; reinstall PyTorch from the cu130 index (or take the nvidia portable) and confirm torch.version.cuda prints 13.0. What the warning costs has not been measured on this card. On a different card, the operator's RTX 5060 Ti 16GB, the same template took 21.4 s from a cold start on the v0.37.0 cu130 portable against 69.4 s on an install that printed this warning (one rig, one operator, unreplicated; cu130 session, cu128 session). That is one install against another, not one flag flipped, and it is a 5060 Ti's time, not this card's. On a second 5060 Ti a user on 2.10.0+cu128 reports in #16470 that the int8 file ran slower than a Q8 GGUF at about 4 MP, and kijai, a ComfyUI collaborator, answered: "You need pytorch with cu130 for int8 models to work properly." A different line, Failed to import comfy_kitchen, is worse: the int8 formats are defined by that package, so fix the import first — pip install -r requirements.txt in the venv restores the pinned 0.2.35.

Edit output is over-sharpened and speckled, or ignores the edit; text-to-image is clean

Issue #16435, under Editing. Set resolution to 1056; 512 was clean in both reports too, but shrinks the references. At resolution 0 the grid the node resolves to is the first reference rounded to a multiple of 32.

Edits are far slower than text-to-image

Most likely the prefix cache found no room and fell back to recomputing every step — see Editing. On the tag, set QwenImage21Cachedtype to int8, or device to cpu, and shrink the references. master has PR #16429's placement fix and also the two open crash reports (next entry), so it is not the first remedy.

On master: Fatal Python error: Aborted

#16443, open, reports a hard abort at 0/25 on image editing / img-to-img, on a git checkout with DynamicVRAM active. Read in full on 2026-09-23 (four comments, the last at 14:08 UTC on 2026-09-22): both people in it have an RTX 5060 Ti 16 GB (the second also has an RTX 3060 12GB), neither has seen text-to-image crash, and both see it only on edits and only intermittently — the second user once the edit resolution went above 1 MP, the reporter with two inputs of roughly 1500×1000 and not since switching to smaller ones. The reporter also launched with --cuda-device 0 to force a single GPU and still got the crash. The stack ends in the prefix cache's takeprefetch at qwen_image21/model.py line 353, which is cache.take on master and other code at the tag; the tag makes the same take/prefetch calls (lines 337–338) but without the block-weight allocation recording that master wraps around the block loop, which is what open PR #16450, without maintainer review, blames. No report of this crash on the tag turned up in the tracker threads read. The second crash, in PR #16481, is under Tag or master?. If you hit either on master, go back to a tag: git checkout v0.37.0, or on the portable update_comfyui_stable.bat, which checks out the newest v* tag — v0.37.1 since 19:12 UTC on 2026-09-22, which changes none of this model's code (Installation, step 1).

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 and closed it as a wrong-encoder mistake. Load qwen3vl_8b_int8_convrot.safetensors or qwen3vl_8b_w4a8.safetensors with type qwen_image — not a qwen3.5_9b_…_pe_… file, which a reader on the repack's discussion #4 reports gives garbled images in that slot.

Expecting value: line 1 column 1 (char 0) while the encoder loads

Reported once, in #16472, loading the template's int8 encoder; open PR #16474 attributes it to a layer whose quantisation marker is empty. kijai replied: "This is most likely a corrupt/incomplete model file." The reporter re-downloaded the file, it loaded, and the issue was closed on 2026-09-22. Check the sha256 against step 3 before anything else.

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

That is the fallback working as designed. On the legacy loader the 2048² decode asks for 8.246 GiB on Windows with the DiT moved off; on the default loader nothing is reserved and the decode's real allocations decide. The decode is slower and the image should be unchanged. On this card no DiT build stays beside a legacy 2K decode once a desktop takes its share: even INT4 ConvRot comes to 3.415 + 0.629 + 7.031 + 0.586 = 11.661 GiB on Windows, which leaves 0.279 GiB of the card for the desktop and the CUDA context together — less than the 1.164 GiB not free in the two error-report readings. What removes the tiling is more free VRAM — close what else is using the card.

Every generation reloads models

Expected when the prompt or the resolution changes, for the take-turns reason under What actually gates this card; at 1024² a seed-only change should not, but at 2048² a seed change may re-stage part of the DiT after the decode (the seed-change figures under the swap above). Those reloads are the trigger of open #16437, which reports that on an RX 9070 XT the first image after a server start is correct and every image after a model reload comes back with its channels in a [B, A, B, A] pattern, until a restart; removing --enable-dynamic-vram fixed it for the reporter, who adds "I don't have an NVIDIA card to test whether this is ROCm-specific." The thread's one other comment is about a different model, and no NVIDIA report of it was found in the tracker threads read. If your images turn green after a prompt change, restart ComfyUI; if it keeps happening, start with --disable-dynamic-vram and use the legacy tables above.

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

city96's node refusing a GGUF with no general.architecture key — leejet's files. Use Abiray's files with city96's node, or leejet's files with leejet's fork, not a mix (Sub-int8 builds, GGUF).

See also: the RTX 5060 page in this series documents the 8 GB install with the w4a8 encoder and the same NVFP4 build; the RTX 5070 Ti page the 16 GB Blackwell budget. The 2025 20B predecessor has its own page for this card, on a GGUF Q3 path the much smaller 2.1 no longer needs — Qwen-Image on RTX 5070.

Sources searched for reports on this card, on 2026-09-23: the ComfyUI tracker — issues and pull requests created since 2026-09-18 matching "5070" (two, both about an RTX 5070 Ti), the 28 threads matching "Qwen-Image-2.1", and the startup-log queries "Total VRAM" "RTX 5070", "GeForce RTX 5070" and "RTX 5070" with posix, linux, GCC or OS linux (bodies and comments of every hit parsed; the only desktop RTX 5070 logs among them are the nine Windows ones above); every discussion on the vendor's repo (37), the Comfy-Org repack (14), Comfy-Org/Qwen3-VL (7) and the NVFP4, INT4, GGUF and turbo repos named on this page; and all 196 comments of the Hacker News launch thread. Reddit was not searched. This is launch week and the tracker moves by the hour; report problems, or better a measured run on this card, 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 5070 (12 GB).

How hard is this setup?

Intermediate — follow the steps above.

next