Is it theoretically possible to have an inverted nLockTime? For example, an nLockTime == 500 prevents a transaction from being included in any blocks before the block 500.
Why isn't there a parameter like nExpireTime == 500 that prevented a transaction from being included in any block over the 500? Would it be theoretically possible to have one or it's a flawed approach for some reason?
This is intentionally not possible.
If a transaction would be valid in block X, we want it (absent double spend) to remain valid in any successor of X. This guarantees that (temporary, otherwise harmless) forks that result in small reorgs will never invalidate unrelated transactions - and they will just be able to be mined again in the new branch.
It also simplifies wallet assessment of incoming transactions. Imagine a transaction that was just confirmed in the last block where it would be valid. 1-block reorgs are infrequent, but not rare. You'd need special logic to detect this and factor the risk of a reorg that permanently invalidates the transaction into the decision of when to accept it. It's even worse for unconfirmed transactions, though there are other issues with those as well.