Nodejs will also move on if io is blocked.
However, since Nodejs queues bits of execution, rather than messages, errors can get lost. So then you have unhandled promise rejections… and then relying on a linter to look for those times you did not write something to catch the error. I was told this is a good feature of the linter.
Contrast that with the BEAM languages. An unhandled error crashes the lightweight process. Any linked process (such as a supervisor) can decide what to do about the crash (restart, or crash as well). We don’t even need liveliness probe (like in Kubernetes) because the supervisor is immediately informed (push, not pull).
You don’t need a linter to make sure it has a sensible default, because this is handled by design.
Nodejs, on the other hand, is error prone, _by design_, even though it does not block on IO either.
No amount of typespecing is going to fix that.