Стоит инструменту импорта перехватить низкоуровневый сбой и заменить его, как в диагностическом журнале остаётся только new ImportFailure("Import failed"). Вызывающему коду незачем видеть сведения о локальных файлах. Но тому, кто разбирает сбой, нужно понять, что на самом деле пошло не так.
Доменное исключение можно оставить, а в его конструкторе передать исходный сбой в Throwable как причину. Java сохраняет эту причинную связь, и публичная категория исключения не превращается в низкоуровневую.
Публичный ответ тогда строится из доменной категории и сообщения, выбранного намеренно. Брать формулировку из getCause().getMessage() нельзя, ведь в причине могут оказаться как раз те локальные подробности, которые мы хотели скрыть. Внутренней диагностике тоже нужны продуманные правила. Указание печатать каждое исключение целиком правилом не считается.
Богатая диагностика тянет за собой правила доступа и маскирования, и эта цена вполне ощутима. Если выбросить причину, этой работы не будет, зато расследовать придётся по двум словам. Я бы выбрал маскирование.