The fundamental flaw of both Modular and Object-Oriented Programming is that they isolate concepts, but not execution.
For the purposes of this discussion I will define program as a set of code which maintains an internal state.
It is generally accepted that developing a program of non-trivial complexity without defects is impossible. This suggests that it is generally accepted that it is possible to write trivial programs without defects.
If one were to write a program by composing trivial defect-free programs it should in principle also be defect free.
The Concurrency-Oriented Programming model of Erlang encourages the developer to build a system from the interaction of isolated processes which communicate through message-passing. A system built in Erlang isolates both concepts and execution. Erlang's exceptional-handling differs from sequential exception-handling in a very significant way: it isolates recovery effort and failure impact to dependent processes.
I believe that Erlang makes it possible to develop nearly defect-free software on a practical timeline.
Newer sequential procedural languages promised to achieve this by supporting Modular or Object-Oriented conceptual decomposition. The overall complexity of the code with access to common internal state it results in is non-trivial. A single bug in a single module or object generally takes down the entire system.
The fundamental flaw of Modular and Object-Oriented Programming in most sequential procedural languages is that they isolate concepts, but not execution. Isolation of execution is left as an exercise for the reader. Achieving reliability in a non-trivial program in these languages requires all of your developers to be well versed in shared-memory concurrency.
Shared-memory concurrent programming is manual and difficult to do correctly. It is also nearly impossible to prove the reliability of systems built in this way. Message Passing concurrent programming is similar to Object-Oriented programming in the way that the programmer separates concepts. The resulting systems have provable semantics. Message Passing is as easy in Erlang as writing a class is in Java.
I believe that retraining a team of Java developers to program in Erlang would be more cost effective than training them in the development of reliable shared-memory systems using Java's concurrency. Shared-memory concurrency is so complex that it is unlikely that the developers would be able to effectively put training into practice given their already complex conceptual workload of actual customer problems that need to be solved.