Local image generation worked for one to three renders, then froze with the GPU pinned at full load. Three reasonable fixes each moved the failure without removing it. The cause was two AI models sharing a 12 GB graphics card that only has room for one. Moving one of them to the CPU fixed it: 22 consecutive renders afterward, no hangs. The deeper cause was that nothing checked whether the models fit before first use.
The setup is two machines on a home network. A Windows desktop with an RTX 3080 Ti (12 GB of video memory) runs ComfyUI with Flux Schnell, an open image model. A Linux laptop sends it requests through a small script and downloads the results. A healthy render takes 8 to 20 seconds.
Flux has two big pieces. A text encoder (about 4.8 GB) turns the prompt into numbers. The image model (about 11.3 GB) turns those numbers into a picture. Together that's roughly 16 GB, on a card with 12.
The first real job was a test batch: a few portraits for Nagi's avatar. That's how the bug surfaced. There were no users before it, so this was a failed launch, not an outage of a working service.
Two Claude sessions worked it: Nagi on the laptop, driving tests, and a second session on the desktop, which built the final fix. This write-up draws on both.
| Time | Event |
|---|---|
| 18:16 | Project starts: Mitch asks how Nagi could make images on request without him in the loop. |
| 18:42 | Setup blocked: ComfyUI's model picker is empty even though the file is in place. The laptop session can't see the desktop's screen, so Mitch moves to a Claude session on the desktop. |
| 19:05 | Picker fixed (cause not recorded) and the render script committed from the desktop. |
| 19:30 | First batch of four renders starts. Each takes about 90 seconds, far slower than expected. |
| 19:38 | Fourth render times out and the desktop's web server stops answering. At the time this was blamed on the machine going to sleep, and Mitch changed the sleep settings. In hindsight it was likely the first hang: same three-then-stuck pattern, and the desktop was on when Mitch checked. |
| 19:40 | Second batch: three renders finish in 7 to 14 seconds each. The fourth hangs. First time the pattern is recognized. |
| 19:43 | An interrupt sent to ComfyUI is ignored. The job stays "running." |
| ~19:46 | ComfyUI restarted. Two fast renders, then a hang with the GPU pegged. |
| ~19:50 | Task Manager during the hang: 16.3 GB of "shared GPU memory" in use. Hypothesis: the NVIDIA driver is quietly spilling video memory into system RAM instead of raising an out-of-memory error, which makes every step crawl. Mitigation: set the driver's CUDA sysmem fallback policy to "Prefer No Sysmem Fallback." |
| 19:56 | Test: two fast renders, then a hang. Same behavior. |
| ~20:00 | Second mitigation: launch ComfyUI with --lowvram. Test: three fast renders, then the fourth hangs. The fourth was the first one with a new prompt. |
| 20:06 | Mitch emails himself the console log from the desktop; Nagi reads it from his inbox on the laptop. It shows the text encoder loading with 0 models unloaded while the 11.3 GB image model stays resident. Root cause identified. |
| ~20:10 | Third mitigation: --disable-smart-memory, which should evict one model before loading the next. Test with six different prompts: five pass, the sixth hangs. |
| 20:14 | Second console log: both models loaded again, sampling at 11.7 seconds per step against a normal 1.4 to 2.4. The flag works most of the time, not every time. |
| 20:23 | Fix, step 1 (desktop session): split the all-in-one model file into its parts. The weights were extracted from the existing file, so nothing new had to be downloaded. |
| 20:32 | Fix, step 2: load the text encoder on the CPU. |
| 20:36–20:41 | Verification: 22 consecutive renders, every one a different prompt, 13 to 14 seconds each. Shared GPU memory stays near zero. Resolved. |
A new prompt needs the text encoder. ComfyUI loaded it onto the card without unloading the image model first, putting about 16 GB on a 12 GB card. Windows' NVIDIA driver doesn't fail when that happens. It quietly moves the overflow into system RAM, so the GPU spends each step waiting on data over the PCIe bus. From the outside, that looks exactly like a hang: GPU at 100%, no progress, no error.
It explains the "fine, fine, then stuck" pattern. Renders that reuse a prompt skip the encoder, because ComfyUI caches its output, so they stay fast. The first render with a fresh prompt brings the second model onto the card and tips it over.
--lowvram. Reduces how much of a model stays on the card, but doesn't stop two models being there at once.--disable-smart-memory. Usually evicted the image model before the encoder loaded. One time in six it didn't. A fix that works most of the time is a mitigation, not a fix.The fix that held removed the competition instead of managing it. The text encoder runs once per prompt, takes a few seconds on the CPU, and has 64 GB of system RAM to itself.
The 22-render test ran with all four changes stacked, so on Oct 7 we took both launch flags back out and re-ran it: 22 of 22 new prompts, median 12.7 seconds, slightly faster than with the flags, and 3.85 GB of video memory left free. The CPU move was the one doing the work.
The same spill showed up once more that evening from a different trigger: ComfyUI started from main.py instead of its launcher, which silently dropped the flags.
The mechanism above answers "why did it hang?" These answer "why did it get this far?" Each chain ends at a gap we own and can change, or at an explicit "unknown, and here's why we stopped."
We took the default template and its all-in-one checkpoint. Nobody added up what has to sit in video memory at the same time. Bottom: there was no capacity check before first use.
The desktop-side check before first use didn't trigger it. Our best guess is that it reused prompts, which ComfyUI caches. Bottom: no acceptance test forced the failure condition. The 22-new-prompt test that proved the fix should have been the gate before launch.
The first hang was blamed on the network. The evidence that solved it, Task Manager and the console log, lived on the desktop. The laptop could only see the web API. The same wall stopped setup at 18:42. Bottom: we deployed with no way to see the machine's state from where the investigation was happening.
The script's timeout gave up locally and left the job running on the desktop, and ComfyUI ignored the interrupt. Bottom: the client had no cancel path.
Its log says it expected the encoder to fit. Stopped here on purpose: finding out means reading ComfyUI's memory code, and with the encoder on the CPU it no longer needs to unload anything.
Each mitigation was tested against a numbered batch with per-render timings, not judged by feel. The Task Manager reading and the two console logs decided the next step each time.
The final test was built to force the failure: every render used a new prompt, the exact condition that triggered the hang. Passing 22 of those means something. Passing 22 repeats wouldn't have.
The console log lived on a machine with no shared clipboard. Mitch emailed it to himself and Nagi read it from his inbox. The workaround took two minutes and produced the clue that solved it. The gap it worked around is still a finding: the same wall had already stopped setup once that evening.
Misread evidence. A failed ping was treated as proof the desktop was offline. Windows blocks ping by default, and it was later failing while the machine was up. The desktop was up. The first hang got blamed on sleep, and that cost a round of diagnosis.
Timeouts that didn't cancel. When the script gave up waiting, the job kept running on the desktop and the next request queued behind it, so one hang turned into a pile-up.
One five-minute test ran in the foreground with no status updates. Mitch couldn't tell a slow test from a hung one, and stopped it to ask. Later in the evening, a progress monitor watched the wrong log file and reported nothing.
Both are now rules: say what a long run is testing and how long it should take, then post a line per step.
| Status | Item |
|---|---|
| Done | Fix. Text encoder on the CPU; image model alone on the GPU. |
| Done | Process. Standing rule for the assistant: long runs get a heads-up, an expected duration and per-step progress. |
| Done | Prevent. Check that a model fits in video memory before first use: each component's size, which ones share the card, headroom. A fill-in template, plus the current setup measured from the console log. |
| Done | Prevent. Make the new-prompt test the gate before any new model or workflow goes live. Now a script: at least 10 never-seen prompts, and it fails on errors, slow renders, blank images or low video memory. Seen both passing and failing before trusting it. |
| Done | Verify. Remove --lowvram and --disable-smart-memory and re-test. Keep only what's proven to matter. Both removed together and the 22-prompt test passed, so neither is needed and one-at-a-time was moot. Both dropped. |
| Done | Detect. Find out why the driver fallback setting didn't apply. Fix it, which would turn a silent hang into a clean error, or remove it. Kept: it's confirmed working now (see section 03). Why it didn't help on Sept 30 is still unknown. |
| Done | Detect. The render script records video memory and seconds per render, and warns on a spill, so the laptop can see what Task Manager showed. With the fallback setting live, a spill is now an error, so it warns when free memory drops under 1.5 GB. It can also pull the desktop's console log directly, which replaces the email relay. |
| Done | Mitigate. On timeout, the script interrupts the job and clears the queue. (First listed as done; it only existed in one night's test loops.) Built into the script, cancelling only its own job so other queued work survives. Tested on a running job and a queued one. |
| Done | Prevent. A launcher that can't start without its flags. (First listed as done; it was a note, and the flags dropped anyway.) A desktop shortcut that runs the launcher, checked from the laptop. The only flag left that matters is network access, and losing it shows up at once as "can't reach ComfyUI". |
| Done | Mitigate. Reserve the desktop's IP address on the router. A changed address would look like ComfyUI being down, the same misread as the sleep theory. Reserved. |
| Won't fix | Built-in retry in the render script. After the fix it hasn't hung once; the batch wrapper's retry is enough. |
Revised Oct 4, 2026 after a 5-whys review: added the setup phase and the second session's findings, split the clock into deployment and incident, reclassified the 19:38 event, and replaced two "done" items that weren't durable. Updated Oct 7, 2026: all eight open action items closed, with the launch-flag test results and the confirmed driver setting.