The problem in fact is in your while loop condition. Let's debug:
When you only input chars that do not match with the pattern [YyNn] all goes ok (user will always get the Incorrect input message). But when you give, let's say an Y, your while loop will stop but Y will not be consumed. Therefore, this char will be consumed in the next instruction, i.e. in String choice = scanner.next(); (if you print variable choice you will see it has an Y).
After this, we go to the next iteration. Because there are no input to be consumed, scanner.hasNext("[YyNn]") will be false. But your while loop condition is !scanner.hasNext("[YyNn]"), which give us a true and enters inside the loop. Inside the loop we have the instruction scanner.next(). Since there are no input to be consumed, BOOM, you get a java.util.NoSuchElementException, which says the following:
Thrown by the nextElement method of an Enumeration to indicate that there are no more elements in the enumeration.
Other of your problems is in your scanner position. At each iteration you are initializing a new instance and closing it. You could just move the scanner initialization and its closure outside the loops.
Below I provide a similar sample code that does what you want with some explanations.
FULL CODE
public static void main(String[] args) {
boolean run = true;
Scanner scanner = new Scanner(System.in); // Init before loops
String userInput = ""; // tmp var that holds input
while (run) {
// do something
System.out.println("Another action? [Y/N]");
userInput = scanner.next(); // Read first time
// Run while user does not put Y || y || N || n
while (!userInput.matches("[YyNn]")){
System.out.println("Incorrect input");
userInput = scanner.next();
}
// User does not want more actions
if(userInput.matches("[Nn]")){
System.out.println("Do you wish to exit the program? [Y/Any other key]");
String choice = scanner.next();
// Stop the program
if (choice.toLowerCase().equals("y"))
run = false;
}
}
scanner.close(); // Close scanner outside
}
Hope it helped!