Three bugcheck codes, two eGPU cables, one replaced dock, and the actual cause turned out to be four bytes in the registry. A debugging log for anyone chasing the same ghost.

Posted At: يوليو 25, 2026 - 189 Views

An AMD RX 9070 eGPU crashing only at idle? Check ULPS first

Nvidia is still the safe default for AI work. The problem is what that safety costs: an RTX 5090 is close to three thousand dollars. Meanwhile I had a mini-PC sitting on a shelf doing nothing but idling on its integrated graphics, and the itch to turn it into a dedicated agentic-AI testing rig won. So instead of handing Nvidia the money, I bought an AMD Radeon RX 9070 for about a quarter of the price, hung it off the outside of the machine through an eGPU dock, and ran the whole stack on AMD's open Vulkan backend rather than CUDA. Then I lost the better part of a month to debugging. This is the write-up I wish I'd had going in.

Here's the short version, in case you're mid-panic and about to RMA something. If you've bolted a discrete GPU onto a mini-PC or laptop over OCuLink or USB4, and it crashes or just quietly disappears, but only after the machine has been sitting idle, never while it's actually grinding on something, the cable isn't your problem. Neither is the dock, or the card. Don't send anything back yet.

TL;DR

  • AMD's driver ships a power-saving feature called ULPS (UltraLow Power State). When the system goes idle, it powers down whatever GPU it has decided is "secondary." It was written for laptops that flip between an integrated and a discrete GPU, and on an eGPU rig it misfires, because your external card looks "secondary" in exactly the sense the driver cares about.
  • Waking the card back up is where it falls apart. What you get depends on the day: a driver timeout, the device dropping off the bus, a full bugcheck, or the whole box freezing with no dump to show for it.
  • The fix is two registry values, EnableUlps and EnableUlps_NA, both set to 0, plus switching off USB selective suspend. No new hardware.
  • The giveaway that it's this and not your wiring: the crashes cluster at idle and never happen mid-workload. That one correlation is basically the whole diagnosis.

1. The setup

The hardware: a Ryzen mini-PC with its integrated GPU, and a discrete Radeon RX 9070 (RDNA4) in an external enclosure on OCuLink, with USB4 on the same dock as a backup path. For compute I skipped ROCm and used AMD's open Vulkan backend. llama.cpp's Vulkan path is solid on RDNA4, and for what I was doing it buried the CPU fallback. None of this is exotic. It's the ordinary shape of an eGPU build on a small-form-factor or laptop-class host: one GPU soldered to the board, one GPU living in a box on the desk.

That ordinary shape turns out to matter, because it's precisely the shape AMD's driver expects to see on a laptop. And it applies laptop rules to it, which is where the trouble starts.

2. The symptoms

One fault wore four different masks over those weeks. If you're digging through Event Viewer right now, these are the ones I kept hitting:

CodeNameWhat it looked like here
0x116VIDEO_TDR_FAILUREThe driver blew past the timeout-detection-and-recovery window, and Windows gave up on the card.
0x10EVIDEO_SCHEDULER_INTERNAL_ERRORLogged with a STATUS_DEVICE_REMOVED parameter. Translation: the card walked off the bus mid-session.
0x7ESYSTEM_THREAD_EXCEPTION_NOT_HANDLEDAn access violation inside a driver thread. Different fingerprint, same underlying cause.
n/aHard freeze, no dumpThe worst one. The machine simply stops. No bugcheck, no minidump, nothing in the log except that damning "previous shutdown was unexpected" on the next boot.

The thread tying all four together: not one of them happened during a stress test, a model load, a render, anything that kept the card busy. Every single one hit after the work stopped. Sometimes a minute later. Once after 21 hours of perfect uptime.

3. What we ruled out first (and how)

Read this part even if you scroll ahead for the fix, because the process is the transferable bit. Everything below is a real, common way an eGPU dies. None of them was my problem, but ruling each one out cleanly is what finally cornered the actual cause.

  • TDR timeout tuning. I pushed TdrDelay and TdrDdiDelay up to 60s. That stopped the BSODs during a deliberately stalled transfer, which was handy, but it was papering over the stall, not removing it.
  • Reseating everything. Powered down, pulled the card, reseated it, reconnected every cable, then bought a fresh cable rated for the link's full bandwidth. The pattern didn't budge.
  • Switching the link entirely. The dock exposes both OCuLink and USB4 to the host, so I tried both. A bad connector on one path shouldn't take down the other, and yet it failed the same way on both. That's a useful negative result: identical failures across two independent physical links point away from a single bad cable or port.
  • Rebuilding the whole stack. On the off chance a stale binary was to blame, I rebuilt the GPU compute stack from source against the current Vulkan driver. Nothing changed.
  • Beating on it. Repeated full memory load/unload cycles, then twenty minutes of continuous heavy requests, back to back. Passed clean. Then it fell over about an hour later doing absolutely nothing. That should have tipped me off sooner: a card that shrugs off real punishment but dies at rest doesn't have a bandwidth or a heat problem.

Takeaway. If your eGPU is bulletproof under load and only ever dies after minutes or hours of idling, put the cables down. This isn't wiring. It's power management.

Every failure shared one trait: it struck after the GPU went idle, never while it was working.

4. The real cause: ULPS

ULPS, short for UltraLow Power State, is a power-saving trick built into AMD's graphics driver. On a laptop with switchable graphics it earns its keep: sitting on battery with nothing demanding running, the driver all but shuts the discrete GPU off and lets the integrated one drive the desktop. Real battery saved.

How it decides is the catch. It looks at whether a GPU is "secondary" to some "primary" one, and that's exactly the relationship between an integrated chip and a discrete card whenever both exist, whether the discrete card is bolted into a slot or dangling off OCuLink in a box on the desk. The driver can't tell those two situations apart. It sees a secondary adapter and reaches for the off switch.

For a real laptop dGPU, waking back up is routine. For a card on the far end of an external, lower-margin link, it isn't, and when the wake fails you get the exact grab-bag from earlier: a timeout, a card that's silently gone from the bus, or a driver thread that dies outright trying to bring it back.

5. The fix

Two registry values and one power setting. Everything here is reversible, and none of it costs you a part.

1. Disable ULPS on the card

Open Registry Editor (or PowerShell) as Administrator and go to the display adapter's driver key:

HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Class\
{4d36e968-e325-11ce-bfc1-08002be10318}\0000, 0001, 0002 …

Each four-digit subkey is one GPU Windows knows about. Open them one at a time, read DriverDesc to be sure you're on the discrete card and not the integrated one (leave that alone), and set:

EnableUlps     = 0  (DWORD)
EnableUlps_NA  = 0  (DWORD)

If the card shows up under more than one subkey, and it often does, do all of them.

Where it gets maddening. If Memory Integrity (Core Isolation / HVCI) is on, Windows guards this particular key against writes. Elevated Administrator won't help. Taking ownership of the key won't help. You just get a flat "Requested registry access is not allowed" and no hint as to why.

The way through: turn Memory Integrity off under Windows Security → Device security → Core isolation, reboot, make the edit, then decide whether you want Memory Integrity back on. The value sticks either way. If you'd rather not go near that setting at all, TechPowerUp's Radeon ULPS Toggle flips the same two values through its own elevated helper, and it's worth a look.

2. Turn off USB selective suspend

OCuLink and USB4 controllers often share silicon on these boards, so close this door too while you're here:

powercfg /setacvalueindex SCHEME_CURRENT 2a737441-1930-4402-8d77-b2bebba308a3 48e6b7a6-50f5-4782-a5d4-53bb8f07e226 0
powercfg /setdcvalueindex SCHEME_CURRENT 2a737441-1930-4402-8d77-b2bebba308a3 48e6b7a6-50f5-4782-a5d4-53bb8f07e226 0
powercfg /setactive SCHEME_CURRENT

3. Reboot

The ULPS change is read when the driver initializes, not on the fly. Reboot once. Don't skip it, or your test will look exactly like a fix that failed.

6. How to actually verify it worked

Almost everyone skips this step, and skipping it is exactly why my version took weeks instead of days. A quick test proves nothing here. The whole failure is about idle, and some flavors of it don't even leave a log; a hard freeze can sit there for hours before you notice the box is gone. Five minutes tells you nothing. An hour of stress testing tells you nothing either, because load was never the question.

What works is boring: a tiny script that writes a timestamped heartbeat to a file every few seconds and just runs, for as long as you can bear to leave the machine alone. Several hours minimum. Overnight if you can.

2026-07-23 21:22:11 IDLE SOAK START
2026-07-23 21:22:11 | GPU=OK | WHEA_total=0 (delta=0)
2026-07-23 21:22:16 | GPU=OK | WHEA_total=0 (delta=0)
2026-07-23 21:22:21 | GPU=OK | WHEA_total=0 (delta=0)
… 9,209 more lines, five seconds apart, zero gaps …
2026-07-24 10:46:57 | GPU=OK | WHEA_total=0 (delta=0)

Two things to look for afterward:

  • Any gap between consecutive timestamps that's meaningfully longer than your sleep interval. That's a stall, even if the system quietly recovered from it, and it means the fix isn't all the way there.
  • Any hardware errors in that window. On Windows, check the Microsoft-Windows-WHEA-Logger source for corrected PCIe errors, which tend to surface before anything else goes visibly wrong.

And because the log is on disk, written line by line, it survives even a total freeze. Come back to a dead machine and the last line tells you exactly when it died.

Checklist, if you're bookmarking this for later

  • Crashes only after idle, never under load → look at power management, not the link.
  • Search Event Viewer for 0x116, 0x10E, 0x7E, and check Microsoft-Windows-WHEA-Logger for corrected PCIe errors.
  • Before you replace anything, set EnableUlps and EnableUlps_NA to 0 on the discrete GPU's keys and turn off USB selective suspend.
  • If the registry write gets refused, suspect Memory Integrity (HVCI), not your own permissions.
  • Reboot before you test. The setting isn't live until you do.
  • Verify with an idle soak of several hours, not a load test. Load was never the problem.

Written up from a real, multi-week troubleshooting log on an AMD Ryzen mini-PC with an RDNA4 card over an OCuLink/USB4 enclosure. Editing the registry and switching off OS security features carries real risk, so know what you're changing and put it back if you don't need it permanently. Your exact keys and paths can differ between driver versions; confirm DriverDesc before you touch anything.