There are many projects that they gave me to maintain that I want to burn and throw away because they depend on everything and the kitchen sink (hundreds of dependencies, and the dependencies also have dependencies) and the developers of most of these dependencies don't care about backwards compatibility, so if you try to update one of these dependencies you end up with cascading failures.
I don't know that I'd say they don't care, as much as backwards compatibility can be hard. In some cases, they literally don't care, but semantic versioning is supposed to help with that, meaning that you may not be able to go from 1.x to 2.x, but you should be able to go from 1.1.x to 1.2.x without breaking changes, and the 1.x branch can continue to receive updates/fixes without worrying about what 2.x does. In fact, log4j sort of worked like that: the 2.x branch broke backwards compatibility, so 1.x was kept around for a while.
But for an example of what I mean by "backwards compatibility can be hard," let's look at log4shell itself. The basic issue is that if user input is logged, it can potentially trigger a JNDI lookup, and a JNDI lookup can potentially be used to download arbitrary Java code and execute it. Why? Well, because of a feature in log4j2 called lookups, one of which is a JNDI lookup. The fix they went with was to default that to off, because JNDI isn't used that often.
But that's essentially a breaking change. JNDI is essentially Java's method of configuring Java apps, which means that turning it off could potentially break logging configurations. Why?
Well, let's get into the real reason log4shell exists: lookups. Lookups could be executed in log messages. This sort of makes sense, because it meant you could log things like environment variables by directly referring to them. But what if you attempted to do something like:
log("User {} said {}", username, message);
When do lookups happen? After the message variables were substituted in.
So if a user said something that contained a JNDI lookup then their message would be substituted into the log message, and THEN lookups would be expanded.
The eventual "fix" log4j2 implemented was to disallow lookups in logged message entirely, which is also a breaking change. (Then again, I don't think it was ever clearly documented that lookups can happen in log messages at all.)
Incidentally, you can't even enter a non-JNDI log4j2 lookup into a Slashdot comment - it triggers CloudFlare's security protections.