- Incorrect use of concurrency stuff like process.nextTick. This function probably doesn’t do what you think it does based on the function name - it won’t “yield to the event loop”.
- for years Buffer and friends was totally busted, these days Buffer has deprecated insecure APIs and uses an internal object pool to avoid the worst of performance issues.
- until Node 12, async stack traces didn’t work and needed to be copied manually for understandable errors.
- anecdotally, whenever I review a popular library I often find some issue where the library papers over incorrectness in order to expose a simpler, more appealing API. For example when I reviewed the popular NPM package execa for executing subprocesses, it put a NodeJS stream based on a Unix pipe into the subprocesses stderr with no way out, even when you request it to connect the parent process stderr directly. This will break with EPIPE if the subprocess writes too much data. But who cares, we get to see stderr in the exception thrown if the command fails, so that’s a nice choice for adoption.
For a taste of how easy and common it is to get this kind of thing wrong, look at this issue in execa from 2019 - stream error handling leads to unresolved promise that hangs forever. Very hard to blame a programmer for using this API wrong. It is so easy to use wrong, and so hard to use correctly. https://github.com/sindresorhus/execa/issues/350