Programmers make mistakes for many reasons, here are a few.
1. The requirements are not clear or complete.
2. The developer is probably not very disciplined. Programming is an exact science. Unless you have worked behind an incredibly detailed oriented coach early in your career, you probably don't try to catch failures before allowing the successful path to execute. The fail first method is a super bug squasher.
3. Lack of command over the language. Knowing the do's and don't for a language like C or C++ can make the difference between bullet proof code vs insecure code or simple vs complex code.
4. Lazy or inexperienced such that the developer seeks success first, instead of hashing out the potential corner cases which takes thoughtfulness; alternatively, purposefully ignoring compiler warnings or failing to perform more in depth static analysis.
5. Fail to seek peer review.
6. Mistakes happen. Simple as that. We are all people and people make mistakes; especially when your tired. Studies have been performed and published demonstrating that people can learn about their own circadian rhythms to find the performance slots and recognize time of day that is less than ideal. Knowing when to work on something complex also creates better results. For me, nothing great ever happened after 9pm except for the re-write the next morning.