2026-07-24 langfuse wrapt Pin Blocks hm switch After Flake Update

What happened

Routine update -c (flake update → check → hm switch) died in the build phase. Same shape as 2026-07-13 Darwin Nixpkgs Regressions Blocking hm switch: a nixpkgs bump moved a transitive Python dep past a pinned package’s ceiling.

The bump raised wrapt to 2.2.2. nixpkgs’ pinned langfuse 4.0.2 declares wrapt = "^1.14" (i.e. <2.0), so pythonRuntimeDepsCheckHook aborted langfuse’s build with wrapt<2.0,>=1.14 not satisfied by version 2.2.2. langfuse is a runtime dep of litellm, so the failure cascaded litellm → home-manager-path → the whole switch. The garnix 504 and does not exist in binary cache lines in the same log were separate transient noise (Nix just falls back to source builds); not the blocker.

The fix

Relaxed the metadata bound via pythonRelaxDeps = [ "wrapt" ] on langfuse in the existing pythonPackagesExtensions overlay in nix/flake.nix, alongside the a2a-sdk and otel entries. Verified end to end: hm switch applied clean, exit 0, containers healthy. Committed as db91399 (bundling the routine flake.lock bumps, since the bump is what necessitated the fix).

What made it a clean call rather than a guess

The deciding check was upstream’s own pyproject.toml, not the nixpkgs error. At 4.0.2 langfuse pinned wrapt = "^1.14", but langfuse main later widened it to wrapt>=1.14,<3 — the maintainers themselves deemed wrapt 2.x a supported runtime for the same code. So relaxing the bound is honest, not a papered-over incompatibility. The reusable rule: on a pythonRuntimeDepsCheckHook failure, read the upstream constraint at HEAD before choosing relax-vs-pin. If upstream already widened it, relax; if it still holds the ceiling, pin the dep instead.

Captured the diagnostic to project memory as reference_litellm_langfuse_wrapt_pin_break — first suspect for any post-flake-update litellm build break.