spoken 2009, about 1965Hoare, on a decision he made
The person who introduced the empty reference into a widely copied language described it in a conference talk as his billion-dollar mistake, and gave a reason that is more useful than the phrase: he did it because it was easy to implement.
That is a recollection given four decades later, and it is the only direct statement of intent available. The design itself is documented in the language report of the period.
What the mistake actually is
Not the existence of a value meaning nothing. Absence is a real thing that programs need to express, and every language expresses it somehow.
The mistake is that it inhabits every reference type silently. A declaration saying a variable holds an account holder is not a promise that it does, and nothing distinguishes the places where absence is expected from the places where it would be a defect.
What that costs
Every use of every reference becomes a possible failure, and the compiler, which is the only thing that could check systematically, has nothing to check against.
The resulting failure is also the least informative kind: it reports that something was absent, at the point where the absence was noticed, which is usually far from wherever the value should have been supplied.
1970sThe alternative that already existed
The other answer is as old as the mistake. Absence is a separate type constructed around the value type, so the two cases are different types and the compiler will not let the empty one be used as though it were the other.
It costs a little ceremony at each use and moves the failure from run time to compile time, which is the entire trade and has been available since the nineteen-seventies.
Why it took so long to change
Because the languages that inherited the design had enormous existing code, and adding a distinction between references that may be empty and references that may not is a change to the type of every declaration ever written.
The languages that did it did so at a version boundary with a migration period, tooling to annotate gradually, and a long tail of libraries that could not be trusted until they were annotated. The cost of removing a mistake grows with the population that inherited it.
2010s onwardsWhere it now stands
Newer languages either have no such value at all, or make references non-empty by default and require the empty case to be written out. Older ones have added annotations, flow analysis and warnings that approximate the same thing without breaking what exists.
Which is the ordinary end state for the entries in this part: the mistake is understood, the fix is known, and the fix is being applied over decades to a population that cannot be updated at once.
The version in unmanaged languages
Worth separating, because the consequence differs. Where the reference is a raw address, using an empty one is not a caught error but undefined behaviour, and what happens next depends on the platform rather than on the language.
Usually it faults immediately, which is fortunate. Where the offset being added is large enough, it may not, and the failure becomes a memory safety problem rather than a crash.
The related decision nobody calls a mistake
A second design choice compounds it. In most languages that inherited the empty reference, it is also the default value for uninitialised fields, so an object can exist in a state its own constructor never intended.
That turns a question about arguments into a question about object lifetimes, and it is why the failure so often appears during construction, deserialisation or dependency wiring rather than at a call.
2010sWhy the annotation approach is only partly effective
Retrofitted schemes rely on annotations, and an unannotated library must be assumed to be either safe or unsafe. Assume safe and the checking is decorative; assume unsafe and every call into old code produces a warning nobody can act on.
Most implementations chose a middle position with a third state meaning unknown, which is honest and means the guarantee holds only within the annotated region.
Why the figure in the phrase is not a measurement
The billion in the name is rhetorical, offered by the speaker as an estimate rather than a calculation, and it appears in this document's part on repeated numbers by implication.
The underlying claim, that this single design choice has produced an enormous quantity of failure over sixty years, is well supported by defect data from many sources. The specific total is not, and quoting it as though it were is the same error the part on numbers is about.
What we cannot verify
The language report is published and the talk is recorded. The attribution of intent rests on the speaker's own recollection, given long after the fact by somebody who knew how it had turned out, which is a category of evidence this document marks wherever it uses it. Defect frequency figures vary by language, corpus and methodology.
In short
- The author called it a billion-dollar mistake and said he did it because it was easy.
- The mistake is not absence; it is absence inhabiting every reference type silently.
- The compiler has nothing to check, so every use becomes a possible failure.
- Making absence a separate type has been available since the nineteen-seventies.
- Removing it means changing the type of every declaration ever written.
- The figure in the phrase is an estimate, and quoting it as measured is its own error.