The thunk trap, why your Nix loop crashes after it finishes

Nix can run loops far beyond its normal recursion limit when builtins.genericClosure is used as a trampoline. But there is a trap. The loop can complete, and only later crash when the result is read.

This lightning talk shows that failure live. A tiny accumulator appears to run in constant stack space, but laziness quietly builds a chain of suspended field updates. Forcing the final field reconstructs the eliminated stack as thunks and overflows.

Then we fix it by forcing exactly the part of the state that the trampoline would otherwise leave suspended. The forcing point is the key field that genericClosure already evaluates while deduplicating worklist items.

If you write large Nix evaluators, validators, generators, or DSL interpreters, stack safe iteration is not enough. You also need to know where your thunks are forming.

Mika Bohinen

Mika Bohinen runs Kleisli.IO, and maintains nix-effects, a pure Nix toolkit for effectful programs and auto-derived validation. He runs the technical infrastructure for the Lie-Størmer Center on the same stack.