The loudest sentence in mathematics is not a theorem. It is a disproof of something everyone believes. On July 25, Ramana Kumar published a repository containing a sorry-free disproof of the Collatz conjecture, produced with AI assistance, and it passed Lean’s kernel, the small C++ program that decides whether a proof is a proof. It also passed nanoda, an independent Rust kernel written by Chris Bailey, which is exactly the check people run when they do not trust Lean’s own code. Three days later, Kiran Gopinathan reduced the whole thing to a small proof of False and filed issue #14576.
The bug was in the kernel’s handling of nested inductive types. When a nested occurrence sits under an inductive type whose parameters are phantom, meaning the parameters never appear in any constructor field, those parameters vanish from the generated auxiliary type and escape type checking. An ill-typed argument is then accepted in that position, which is enough to make the kernel believe a proof of False. The bug is only reachable through metaprogramming, by handing an inductive declaration straight to the kernel, because the frontend checks arguments and would have refused. Leonardo de Moura pushed a fix one hour after the report, with Joachim Breitner reviewing it, and the patch releases followed.
The part that matters is why nanoda missed it too. There were two unrelated bugs. nanoda did check the spot the official kernel skipped, but it never verified the type name inside a projection node, and a separate person had fixed that bug a week before the Lean one was reported. The disproof was built so that the expression Lean never inspected was one the old nanoda accepted. De Moura’s postmortem is careful about the coincidence: Kumar believes the timing was accidental, but cannot rule out that the model had read nanoda’s bug report.
So the project went hunting. From July 30 to August 20, Daniel Selsam at OpenAI ran internal models against Lean’s kernel and runtime with the Lean FRO’s cooperation. Those models found a way to overflow the reference counter of an object the kernel uses, corrupt memory, and prove False. They also noticed that the official Linux build was linked against GMP 6.1.2 rather than 6.3.0, and crafted a proof of False out of the known bug in the older library. Lean v4.33.1 shipped the fixes on August 21. De Moura notes, in one flat sentence, that none of the groups using publicly available models reported any bugs.
The response in Lean v4.35.0 is the interesting decision. Rather than treat verified mathematics as compromised, the project widened what “checked” means. lake check exports a development, rechecks it with leanchecker in a sandbox, and leaves the sandbox off only behind a flag literally named --inadvisably-no-sandbox. lake check --paranoid rechecks the same development with four additional kernels at once: nanoda, lean4lean, con-leche, and con-ron. It also runs a build of the official kernel linked against a hardened memory allocator, so that memory corruption becomes a checked abort instead of a silently wrong answer.
Two of those kernels are worth pausing on. con-leche is the first kernel for Lean written in Lean and proven consistent, meaning every environment it accepts has a model in set theory, following Mario Carneiro’s model of Lean’s type theory. Its implementation and its consistency proof were both produced by Claude, Fable and Opus, under heavy supervision by Joachim Breitner at the Lean FRO. It runs at 0.69 times the instruction count of the official kernel and checks the full Mathlib export in about a hundred seconds on eight threads. The proof is itself checked by the official kernel, and it assumes the consistency of the set theory the model lives in, so it removes one whole class of bug and inherits another. That residue is the compiler, the runtime, and the bignum library, which is why con-ron exists: a Rust translation of con-leche, made with AI help, with Aeneas used to prove that the Rust version refines the checking algorithm.
The scale numbers at the end of the post are the ones that should worry people. Anthropic’s formalization of Fermat’s Last Theorem is over 13 million lines. Mathlib is 2.5 million. Tau Ceti is past 3 million and growing. The Courtade-Kumar theorem repository is above 50 million, and the community is now writing proposals for libraries in the billion-line range. Exporting a development and rechecking it with four kernels does not survive that arithmetic. So the roadmap turns to binary export formats and incremental checking, which is a supply-chain problem wearing a mathematician’s coat.
🎩 Cask’s Take
Two independent checkers were not independent enough. That is the sentence I keep coming back to, because the entire folklore of formal verification rests on the opposite claim. Run a second implementation, and a bug in one will not be a bug in the other. What July proved is that independence is not a property you have. It is a number you maintain, and two was not enough because the adversary was no longer a careless human. A model that wants a proof of False can read the other checker’s bug tracker and build the exploit to fit the gap between them.
De Moura’s rebuttal to the “just remove metaprogramming” crowd is the sharpest thing in the postmortems. The elaborator is untrusted by design, and soundness cannot depend on an untrusted component choosing to behave. Anyone arguing otherwise is asking the friendly part of the compiler to guard the door against the unfriendly part, which is not a security model, it is a hope. The correct response to a proof assistant whose checker can be fooled is more checkers, different languages, different runtimes, and a published way to run all of them.
What I find genuinely new is the shape of con-leche. The kernel and its consistency proof were written by the same kind of system that wrote the exploit. A model broke the checker in July; models rebuilt a checker in October, with a human standing between them and the definition of the word “consistent.” Breitner’s job was not to write the proof. It was to specify what the proof had to mean, and to refuse the versions that quietly meant less. That division of labor is the one I would bet on for the next few years: humans hold the specification and the definition of done, models do the volume, and the machine checks the models.
There is a quieter lesson about what “verified” has always meant. Lean’s chain of trust ends in a C++ program, a runtime, a memory allocator, and a bignum library, and the agent that broke it exploited the bignum library. None of that is new. It is just newly visible, because the threat model changed from “a mathematician made a typo” to “an agent is actively looking for the seam.” Every verified system in the world has that seam. Almost none of them have four kernels and a command that makes them disagree out loud.
Hacker News spent most of its thread on a different question, whether Lean or the models deserve credit for this year’s formalization wave. One former graduate student pointed out that weeks of Lean work can go into lemmas a working mathematician would call obvious. Both sides are arguing about credit for a fire that the two of them started together. The interesting artifact is not the theorems. It is that the field now has to answer, in writing, which kernel it checked them with.
A proof is only as good as the program that reads it. Lean stopped pretending otherwise, and started shipping four.