Garbage-collected languages and memory allocation failures
Here is a thesis, in light of something I've seen recently: one of the weaknesses of today's high level dynamic languages is that they have basically no good way of handling being unable to allocate more memory. In fact I think this applies to pretty much any language that assumes garbage collection and automatic memory management.
There are two problems. First, dynamic languages only rarely allocate memory in more or less explicit ways, in operations which can already fail for other reasons (and thus your code already needs to be prepared for them to error out). Second, dynamic languages need to allocate memory in order to do very much of anything within the language.
The first problem effectively breaks the language semantics when memory allocation failures start; operations that should not fail start failing. Adding a key to a hash, concatenating two strings together, or even subtracting one number from another are now things that can make your code die. Almost every line and every statement can be a failure point. How do you possibly cope with that gracefully?
(This is where functional programming and other approaches where you never mutate data structures in place might have an advantage, because with care you can know that your core data structures are always intact. (Assuming that the language runtime itself properly copes with memory allocation failures halfway through operations like rebalancing the innards of a hash.))
The second problem means that there is often nothing that you can do to recover. If your process flat out cannot allocate more memory, your recovery code needs to operate in such a way that it doesn't need more memory, ie it cannot allocate new objects or even mutate existing objects in such a way that requires more memory for their internal implementation. Often this is simply impossible, because the language allocates new objects (such as call frames) as part of running your code. When it's not outright impossible it requires either extreme care (and a very deep understanding of your runtime environment) or strong care and support from the language implementation itself (eg to provide a reserved last-chance memory allocation arena that is only used when the out-of-memory recovery code is running). Either are at least challenging to implement.
Languages with explicit memory management avoid both issues (and the more explicit the better). Potential failure points are hopefully both relatively infrequent and visible, and at least in theory recovery code can run without needing memory allocations.
(There are practical difficulties, partly because many libraries assume that they can do memory allocations for internal purposes. You're probably not going to be throwing up GUI notifiers no matter what language your program is written in, for example.)