An old software project can survive in GitHub, compile nowhere, and still look perfectly preserved to anyone browsing the source.
The missing piece is often a dependency.
Modern projects rarely contain every component they need. Instead, they name packages hosted elsewhere and ask a package manager to download the exact versions during installation or build time. If one of those versions disappears, the project may become unreproducible even though its own repository is untouched.
The most famous demonstration arrived in March 2016, when a developer unpublished a collection of packages from npm, including the tiny left-pad module. npm’s own postmortem, “kik, left-pad, and npm”, acknowledged that unrestricted unpublishing had allowed one removal to disrupt dependent software and promised policy changes.
A lockfile can describe a missing thing
Lockfiles help reproducibility by recording precise dependency versions instead of accepting whatever happens to be current. That is useful, but a lockfile is not an archive.
If package-lock.json, yarn.lock, Cargo.lock, or another lockfile says a project needs version 1.2.3 of a package, the build is only reproducible if version 1.2.3 can still be obtained. The lockfile can tell you exactly which brick is missing. It cannot manufacture the brick.
The left-pad event made that distinction painfully obvious. A vast dependency graph had been built on the assumption that registry entries would remain fetchable. When one small package vanished, the failure propagated far beyond the original author.
npm responded by tightening removal rules. Its follow-up on changes to the unpublish policy made dependency impact part of the decision. The current npm unpublish policy continues that approach: older packages can be removed only under limited conditions, including having no dependents in the public registry.
Reproducibility requires preserving dependencies too
There are several ways to reduce the risk. Organizations can maintain registry mirrors or caches. Projects can vendor critical dependencies into their own source tree when licensing permits. Build systems can use artifact repositories that retain the exact packages used for releases. Preservation projects can archive both source repositories and the package ecosystems around them.
Even that is not perfect. Old dependencies may require obsolete compilers, operating systems, certificate chains, or package-manager behavior. A package file may survive while the service needed to resolve it does not.
That is why preserving software is harder than saving source code. The program may be a small island connected by hundreds of bridges to other projects. If enough of those bridges disappear, the island is still visible. You just cannot get there anymore.
