And of course that guarantee has its own problem, namely that (especially in a multithreaded process) a use-after-close error is vastly more likely to cause corruption via a write to a newly opened file in the old file descriptor.
And in all fairness, nobody was thinking of multithreading when these APIs were designed. We're lucky enough that errno mostly works as a thread local rather than a global.