DEV Community

Cover image for Five Wrong Root Causes, and the Fifth Was in the Post
Erik Hill
Erik Hill

Posted on

Five Wrong Root Causes, and the Fifth Was in the Post

I wrote most of a post about how a failing system's logs seduce you into confident wrong root causes. Then I committed one, in the post itself. Within an hour of publishing, the maintainer of the Wine packages I had written about corrected me in the open.

This is the whole arc, including the part where the instrument I trusted most was the one that lied.

The setup

The Wolf Among Us: the macOS build is 32-bit, dead since Catalina. The Windows build runs under Wine, but it is wrapped in Steam DRM, so a logged-in Steam client has to run in the same prefix. The real boss fight is therefore: log into Steam, under Wine, on a Mac, in 2026.

Stock Wine could not do it. The login page rendered sometimes, polled forever, and died:

Login: Failed to poll auth session. Result 2. Transport Error: 2
Enter fullscreen mode Exit fullscreen mode

Four wrong answers I caught myself

Every one of these was supported by the failing system's logs:

  1. Winsock. Unknown error 10045 (WSAEOPNOTSUPP) sat right next to the failing poll. Obvious. Wrong.
  2. The CEF sandbox. Disabling it changed nothing, and one flag deleted the UI, which I briefly celebrated as a new bug.
  3. Missing Gecko. I "confirmed" Wine's HTML runtime was absent by searching only the working system for it. It was present in both. A one-sided search dressed up as a comparison.
  4. GL/ANGLE. Real errors, and forcing software rendering removed them completely. Login still failed at the same rate.

The instrument that broke the tie felt authoritative: diff a working system against the failing one. CrossOver logs the same winsock noise and logs in fine.

signal stock Wine (fails) CrossOver (works)
WSALookupServiceBegin failures 30 5
10045 errors 15 2
failed auth polls 24 0

Anything present in both is noise. What remained on only the failing side was two fixme lines I had scrolled past all night:

fixme:bcrypt:export_asymmetric_key unsupported blob type L"OpaqueKeyBlob"
fixme:ncrypt:map_ntstatus unhandled status 0xc0000002
Enter fullscreen mode Exit fullscreen mode

Upstream Wine dropped its gnutls-backed bcrypt after 11.6, and the rewrite never implemented opaque export for asymmetric keys. It is still unimplemented in master. That gap is real. I filed it: WineHQ 60214.

The part that actually worked

I got a Steam-DRM game running on a fully free stack: a GPTk-based Wine (which ships Apple's D3DMetal) plus an archived early-2025 Steam client old enough to predate the heavier client. Login by phone confirmation, library loaded, game ran. Verified, witnessed, screenshotted. I also revived the discontinued Whisky app from its archived runtime, which is the one piece of this whole night nobody has disputed.

So I published. Wrote it up, filed the bug, posted the thread. Felt good.

The fifth wrong root cause

Within the hour, Gcenx, who maintains the official WineHQ macOS packages, replied. Two of my claims did not hold up.

One: I said only Apple's D3DMetal could solve the rendering wall, that the community DXMT layer was a dead end because I hit a cross-process swapchain error. Wrong. Gcenx and YupItzAfi run the current Steam client with a rendering fix alone: a small steamwebhelper wrapper forcing --in-process-gpu. Gcenx does it on the MoltenVK path; DXMT is a separate self-compiled-Wine route. I had hit the same wall and quit early, because I passed the flag to Steam.exe instead of into steamwebhelper.

Two, and this is the one that matters: I framed the bcrypt gap as the cause of the login failure. It is not proven. Gcenx has the current client working via the rendering fix alone, which means rendering, not the crypto gap, may be the real blocker. My own attempt to isolate the two was inconclusive. The API gap is real; its role as the Steam login cause is not.

Sit with that. The differential diff, the instrument I had just praised for cutting through four wrong theories, produced a fifth wrong theory. It felt like the answer because it was cleaner than the others, not because it was proven. Clean is not the same as correct.

What I did about it

Corrected every surface the same hour. Retitled the WineHQ bug to describe the verifiable API gap and stop implying it was the Steam cause. Refocused and renamed the repo to what it can honestly stand on, the bug and this post-mortem, and pointed anyone who wants to actually run Steam at the maintained path: the official WineHQ packages plus the steamwebhelper wrapper. Credited Gcenx and YupItzAfi, who were right and generous with their time.

Nothing had to be redacted, because the verified core held: the game did run, Whisky did revive, the API gap is real. Only the interpretation was wrong, and interpretation is exactly what a differential diff cannot certify. It tells you what differs. It does not tell you which difference is the cause.

What I am keeping

  • A failing system's logs support every theory you bring to them. Four of mine, equally.
  • The instrument you trust most is the one to distrust hardest. Mine handed me a confident wrong answer wearing the costume of rigor.
  • Being right was never the measure. Four wrong causes I caught; the fifth I shipped, and someone better-informed caught it. What I could control was how fast and completely I fixed it.

That last part is the whole discipline, and it is the only reason this is a post I am glad I wrote rather than one I wish I could delete.

Top comments (0)