---
name: windows-lock-contention-is-not-wouldblock
description: "a contended fs2 try_lock on Windows returns raw OS error 33 with ErrorKind::Uncategorized, NOT WouldBlock — matching on the kind turns every contended acquire into an instant hard error, i.e. the exact fail-fast the lock was built to remove"
metadata: 
  node_type: memory
  type: reference
  originSessionId: a4c12adc-aeca-46be-8433-9a2ac2e20d5e
  modified: 2026-08-25T13:38:13.536Z
---

`fs2`'s `try_lock_exclusive` reports contention **differently per platform**, and the portable-
looking predicate is the wrong one on Windows.

Measured 2026-08-25 (FIELD-SEAL W3, `spt-store/src/wtlock.rs`): a second handle on a held file
returned `Os { code: 33, kind: Uncategorized, message: "The process cannot access the file
because another process has locked a portion of the file." }`. My acquire loop matched
`ErrorKind::WouldBlock` as "keep waiting" and returned every other error immediately — so on
Windows a contended acquire failed INSTANTLY as a hard error, which is precisely the fail-fast
behaviour the lock existed to replace.

**The predicate that works on both:**

```rust
fn is_contended(e: &io::Error) -> bool {
    e.kind() == io::ErrorKind::WouldBlock
        || (e.raw_os_error().is_some()
            && e.raw_os_error() == fs2::lock_contended_error().raw_os_error())
}
```

`fs2::lock_contended_error()` is the platform's own answer to "what does contention look like
here" — compare against it rather than enumerating codes or trusting `ErrorKind`.

**The generalisable half:** an `ErrorKind` is a PORTABILITY ABSTRACTION, and `Uncategorized` is
what a real OS error becomes when the std mapping has no bucket for it. Any `match e.kind()` over
a platform-specific failure is a guess; the raw OS error is the measurement. Two red units
(elapsed-wait and timeout-refusal) caught this on the first run — which is the case FOR writing
the load-bearing wait arm before trusting the lock, not after.

Kin: [[dont-take-a-diagnosis-as-measured]].

2026-09-08 face (todlando measured, hertz recording) — **`0xc0000142` from link.exe is DLL-INIT-FAILED
UNDER LOAD, not a broken toolchain.** A link step died `error: linking with link.exe failed: exit
code: 0xc0000142` on a contended shared box; it was the SECOND occurrence that day, the first on a
cold build killed under the same conditions. **The danger is the text it presents as:** the usual
advice for that code is "the Visual Studio build tools may need repairing", so a reader takes a
LOAD symptom at face value and goes off repairing a toolchain that is fine. On a box that is also a
CI runner, treat 0xc0000142 as a contention reading first — check the box-wide builder census and
re-run quiet — and only suspect the install if it reproduces on an idle box. Kin: this entry's own
lesson that an OS error code routed through a portable abstraction stops meaning what it says.