Dependencies do break because they are unmaintained. All the time. If it worked ten years ago, there is no guarantee whatsoever that it will work now, unless you:

(a) run it in an environment of ten years ago (otherwise other platform dependencies may be unavailable, or platform behaviour may have changed);

(b) ensure that environment is already fully set-up (otherwise internet systems from which it fetches other dependencies may be unavailable, e.g. due to a service being taken down or certificate changes); and

(c) are using strictly offline-capable software (e.g. if a commercial library does an activation/licensing server check, that may fail).

In other words, to be confident, you need to freeze a snapshot of the entire system, which is obviously terrible for security.

If these conditions are not met, things may or may not work. Some platforms will be more robust over time than others. Scripting languages are generally atrocious, with an installability half-life well under ten years (I’m going to guess something around five years). Compiled languages are a mixed bag. Rust is one of the best options out there, so long as it’s pure Rust code only and doesn’t include any bindings on more build-fragile code.

I shall give a few examples of the sorts of problems that can occur and have occurred to me in the last decade.

• In 2012 I wanted to install IE6 on a Windows 2000 machine (don’t ask). But the underlying infrastructure at Microsoft was gone, so even if I had the full installer, it failed to install.

• A few years ago I wanted to install something that depended (transitively) on some key foundational Perl package, but due to recent Linux kernel changes that package’s tests no longer passed. (Perl defaults to running the tests when you install. You can disable that, but clearly the software isn’t running as expected.) Fortunately the package was maintained, so I just had to install the newer version, overriding the stated dependencies.

• You could be trying to install something with Node.js and it doesn’t work beyond Node 0.12 or 4 or something, so you’ll need to figure out how to get that old version of Node before you have any hope of running the project. And that probably means “figure out how to build it from source”, which is harder than you might hope, because it probably depends on old versions of libraries that used to be easy to get from your OS’s package manager, but are now unavailable, so you’ll have to build them from scratch too, recursively.

• I used to use Hyde to generate my website. A couple of years ago, five years or so after it was abandoned, it had become very tedious at best to install anew, due to being part of the declining Python 2 ecosystem. A few years ago I think I tried setting it up on Windows and gave up after a while, though that’s hardly a fair comparison on its own. On my server, I had used https://aur.archlinux.org/packages/hyde-git to install it, but that’s no longer installable, because it depended on packages in the community repository that have been removed and have not resurfaced in AUR. This is probably not insurmountable, as you can probably install the package in other ways, but it indicates that the way that I had installed it has broken.

I had two or three more examples in mind, but I’ve just been called for lunch.

So just one more note: use lockfiles, they’ll normally make things more robust, but be ready to need to update some of those dependencies in order to get things to work at all a few years down the track, and you’ll be practising trial and error over which.