Your code must have a uniform way to signal errors. In Java/C# this is done by throwing an exception, full stop.
You can use exceptions, but exceptions come with their own problems that are worse than NULL pointers in many cases.
Unless you're talking about the performance implications in C++, that debate was settled last century. Exceptions are the right way to signal errors, because the problem of forgetting to check for errors is endemic. Exceptions translate "I don't handle errors" to "abort", which is obviously the correct translation.
In C code, the return value is consumed by the error code, and any values have to be returned by output parameters. If done this way uniformly, you can at least try to catch the places where people forget to check in code review.
Just returning "null" because you don't have a standard convention for returning errors is the most wrong answer. Null for a potentially expected case is different (like an object not found in a map) - then it actually makes sense, rather than being a hack to avoid error handling.