x1zz.

blog / 2026-09-28 · 4 min

Three open Burn PRs, and a CI failure that wasn't mine

#rust#open-source#burn#ci

I had three PRs open against tracel-ai/burn and none of them were moving. The natural assumption is that something is wrong with the change: a failing test, a review I hadn’t answered, a design the maintainers didn’t want.

It turned out to be none of those. The reason two of them could not merge had nothing to do with the code in the diff — the required CI check they depend on was already failing on main, before my branches existed.

This is how I found that out, and how a one-line lockfile change unblocked every open PR in the repository.

What “mergeable: blocked” means

GitHub shows mergeable_state: blocked when a PR can’t merge, but it doesn’t say why. The why lives in the repository’s branch ruleset. Burn requires one approving review and a fixed set of status checks, including the Windows test jobs. If any of those checks isn’t green, the PR stays blocked no matter how correct the code is.

So the first thing I did was stop guessing and enumerate: list the required check names from the ruleset, then list the actual check runs on each PR’s head commit. For the Bluestein FFT PR (#5757), all fourteen required checks were green — its only blocker was that no human had approved it. For the other two, the Windows checks were failing.

The failure was inside a dependency

The failing job’s log ended with an error that had nothing to do with my diff:

error[E0308]: mismatched types
error[E0277]: the trait bound `ResourceCategory: From<&D3D12_RESOURCE_DESC>` is not satisfied
error[E0277]: the trait bound `&ID3D12Heap: Param<ID3D12Heap, InterfaceType>` is not satisfied
error: could not compile `wgpu-hal` (lib) due to 10 previous errors

wgpu-hal is not my code; it’s a graphics dependency of Burn. The compiler was seeing an ID3D12Device from one crate and a Direct3D12::ID3D12Device from another — the same type, from two different versions of the same crate.

Two versions of windows

The windows crate is versioned in a way that makes different minor versions incompatible, so mixing them produces exactly this kind of type mismatch. wgpu-hal builds against windows 0.62.2. gpu-allocator — which wgpu-hal calls into on Windows — had been resolved to windows 0.61.3.

gpu-allocator’s own requirement allows versions up to 0.62, so its resolution isn’t wrong in isolation. What happened is that a cubecl/cubek dependency bump (#5854) caused Cargo to re-resolve the windows graph, and it chose to unify gpu-allocator onto 0.61.3 to share a version with another crate that needs that exact line. That saved one duplicate crate and broke the DX12 backend.

This is a recurring pattern in the repository: the same class of breakage had already been fixed once in #5735 after an earlier cube update, and the newer bump reintroduced it. When the lockfile is the bug, it reproduces identically for everyone — which is why the failure was red on main, not just on my branch.

The fix

One line in Cargo.lock: give gpu-allocator back the windows version wgpu-hal actually passes it.

The important part is proving that line is sufficient. I cross-checked the exact unit CI fails on, without needing a Windows machine:

cargo check -p wgpu-hal --target x86_64-pc-windows-msvc --locked

Against main’s lockfile it produces the same ten errors. With the one-line change it finishes clean. I also stashed the change and re-ran it to confirm the errors come back — otherwise “it compiles” could be true for the wrong reason.

I sent it as a standalone dependency fix, #5867, rather than bundling it into the feature PRs: unrelated lockfile churn inside a feature diff is exactly the kind of thing a reviewer rejects.

What I’d check first next time

The lesson isn’t “dependency bumps are scary”. It’s about where to look when a PR stalls:

The instinct to assume “it must be my code” is usually right. But when a shared repository is moving under you, it’s worth checking whether the ground is broken before you doubt the code.

← all posts© 2026 · x1zz