some refactoring, plus custom exception