Usually, it is a best practice to write constructors so that they should not have any side effects and external interactions. Just initialize the members of the object using only the parameters passed to them and do all of the complex operations in a separate function once the object was safely constructed.
Or even better, let the only way for constructing an object be a factory function, that can check the parameters for correctness and only create the object if it can be sure it will be valid/consistent/safe to use.
Allowing constructors to do much more than that might have its roots both in history and in offering powerful options to developers (though these overlap a lot).
On the “being powerful” side:
Most programming languages prefer to offer many possibilities for developers, instead of restricting what they can do for a simple reason: If you would need to do something the language does not support you will use a different language … but if you have much more power than needed, you can always decide to be careful and not use it.
On the “historical” side:
Technically, constructors have been just simple functions for a long-long time with some additional rules. This made them easy to implement for compiler developers (other some extra checks they could just reuse the usual procedures used for functions), but also offered all of the powers of “normal” functions.