In write skew each transaction checks a condition, finds it satisfied, and writes somewhere the other one did not look — individually legal, jointly impossible, which is why snapshot isolation alone cannot catch it. Overwriting the same row is a lost update, seeing a changed value on re-read is a non-repeatable read, and reading uncommitted data is a dirty read, which PostgreSQL never permits.
Official docs