Because the way a table is built may depend on other factors like the allocation of other objects and the actions performed by the garbage collector, which may compact the internal representation separately (This would not invalidate the currently open iterators, but may affect the way a new iterator on the same table could operate, as it may start iterating on another item, or could traverse the internal tree in different branches structured differently; notably because a tree-like representation may contain pages randomly ordered by hashes, the iterators keeping only a "snapshot" of the current pages being traversed).
Lua does not formally define how tables are structured, and even the existing implementation does not document the two parts of the table (indexed by integer, or hashed), and these two parts may be restructured at any time by the garbage collector moving some items from one part to another (and it can do that safely when the table has no iterator currently open on it).
You may also have background threads or coroutines adding and removing temporary items in the table: if the thread/coroutine is yielded to another, they can change the backing store, the total number of nodes could increase or be reduced only in free nodes, while not changing the number of used nodes. As well a compactor may change the internal hashing functions depending on the fill rate or total size allocated, it could rebuild the collision lists.
There's already been multiple implementations of tables in Lua, and the specs allow for new implementations. The only contract is that no items should be iterated twice in the same traversal, and that all items in the table should be iterated (as long as the set of items is not extended or reduced, i.e. the set of distinct keys; note that this last set is unordered, this is just a set).
... or filesystems for files or subdirectories in a directory). It is important to know how iterators are implemented and what they keep in their current state to respect the contract.