In .NET and Java it costs at least 100x as much time to throw an exceptions as to return an error code.
Other languages may have cheaper exceptions, but for many mainstream languages, you pay a big performance price for exceptions.
That price is often offset by other positive things, so the tradeoff is made willingly and with eyes open.