This isn't a entity system specific issue; this pattern of versioned or salted handles can be used in almost any generic data structure (e.g., Sean Middleditch's slot map example). Related is the fact that you don't need to use this kind of versioned handle system in an entity/component system, either.
That said, your concerns are valid, but not quite as dire as you may think.
The purpose of the version bits are to allow you to differentiate between stale references to objects. The version bits don't actually have to impose an upper limit on the number of times the slot can be reused. You can make them do so if you like, but generally rolling over the version bits from the maximum value will not immediately crash you.
Once the version bits roll over, however, you can't reliably detect those stale references. If you allocate slot 10, version 0 to object A at the start of the program, and then release object A some time later, any handles referring to slot 10, version 0 are stale. You can detect that when you try to use them, since slot 10 will actually be at version 1.
If, eventually, you execute long enough to roll the versions over so that object Z ends up slot 10, version 0 and you happened to have kept a stale handle to object A around that long without dereferencing it, then at that point you won't be able to tell that that handle to A is stale. It will quietly, safely, dereference to object Z.
The likelihood of this occurring is exceedingly small. Small enough that it's generally not worth worrying about, given the value of the other benefits of this system.
You can help this by accounting for hysteresis. When you build the system, a simple approach is to use a stack of "free" slots. When you go to allocate, just pop the top entry off the stack, right? The problem with this is that if you allocate and destroy frequently, you tend to quickly increase the version of one slot. This can cause you to roll over the versions sooner. If instead you use a queue approach, you can distribute the versioning over a wide range of slots.
The downside is that this can tend to spread your data around in memory, and that can harm cache coherency if you iterate the data often (and if you don't use any kind of skip field, you can burn a few cycles iterating across dead slots as wellalthough this is not without its own drawbacks).
You have to examine the expected use cases and decide which approach to reusing slots fits your case the best.