I do not know what answer they wanted to hear from you at the interview, and it seems to me that there can be no absolutely correct criterion.
My opinion: you need to catch an exception in the place where you know what to do with it .
I will explain.
Suppose you have a function to open a file, a file was not found, and it throws an exception. What to do at this point?
This is an important operation, it is impossible to continue without information from the file, so you need to inform the user and end the program? Or is it a configuration file that the program does not have at the beginning of its operation, and it will need to be created with default data?
In the function of opening the file you do not know. Therefore, it is not necessary to catch an exception, let it fly to a higher level. But at the level of more large-block logic, which launched a configuration read operation, it is possible to catch an exception when opening a file and catch it and simply create a default configuration.
Such a one-tier scheme may be too simple, and you will have to repackage an exception on your way, adding meaning to it. For example, when reading a number from a string, an exception occurred because of a format mismatch. You do not know at this point whether this problem is fatal, and simply skip the exception further. The higher-level logic knows that a configuration data reading operation is taking place, which for some reason ended with an exception. At this point, the program's logic has the ability to decide that the problem cannot be ignored, and it throws a higher-level exception, which means “the configuration read has completed abnormally”. This exception, in turn, catches the top-level business logic, which informs the user about the loss of the configuration file and recreates it again.
In any case, premature catching of exceptions at a too “internal” level is harmful, because a program at such a point usually cannot do anything reasonable.