NoSuchElementException is one of the most frequently encountered runtime exceptions in Java development. It occurs when your code attempts to retrieve an element that simply does not exist, whether from an iterator that has run out of items, a scanner with no remaining input, an empty optional, or a queue with nothing left in it. This article walks you through each common cause of this exception with a broken code example, the exact error output you will see, and a clean working fix. By the end, you will know exactly why this exception is thrown in each situation and how to write defensive JavaScript code that prevents it from happening in the first place.

What is No Such Element Exception
No Such Element Exception is a runtime exception in Java that lives in the java.util package. It extends RuntimeException, which makes it an unchecked exception, meaning the Java compiler will not force you to handle it with a try-catch block or declare it in a throws clause. Because of this, many developers do not realize it can occur until the application actually crashes at runtime.
This exception has one clear meaning you asked Java to give you an element, but there was no element to give. Java does not silently return null in these situations. Instead, it throws this exception to let you know that your code made an incorrect assumption about the availability of data.
What Causes No Such Element Exception
The exception is triggered in several specific scenarios. The most common ones involve iterators running out of elements, scanners finding no more input, optional objects being accessed without verification, queue operations being performed on empty queues, and stream operations returning empty results that are accessed unsafely. Each of these has a clear and distinct fix that we will cover one by one.
Iterator Exhaustion
When you use an Iterator to loop through a collection and call next() after all elements have been consumed, Java throws NoSuchElementException. This often happens in manual loops where the programmer forgets to guard the next() call with a check. The iterator keeps its position internally and once it passes the last element, calling next() again has nowhere to go.
The Broken Code:
java
import java.util.*;
public class IteratorExample {
public static void main(String[] args) {
List<String> names = Arrays.asList("Alice", "Bob", "Charlie");
Iterator<String> iterator = names.iterator();
// This will throw NoSuchElementException after "Charlie" is printed
while (true) {
System.out.println(iterator.next());
}
}
}
The Error:
Alice
Bob
Charlie
Exception in thread "main" java.util.NoSuchElementException
at java.base/java.util.AbstractList$Itr.next(AbstractList.java:372)
at IteratorExample.main(IteratorExample.java:9)
The Fix:
Always call hasNext() before calling next(). The hasNext() method returns true if there are more elements remaining in the iterator and false when all elements have been consumed. This single check completely prevents the exception from occurring.
java
import java.util.*;
public class IteratorExample {
public static void main(String[] args) {
List<String> names = Arrays.asList("Alice", "Bob", "Charlie");
Iterator<String> iterator = names.iterator();
// Correct and safe approach
while (iterator.hasNext()) {
System.out.println(iterator.next());
}
}
}
Output:
Alice
Bob
Charlie
No exception is thrown because next() is only called when hasNext() confirms that an element actually exists at the current position.
Scanner Running Out of Input
The Scanner class is commonly used to read user input from the console or to read content from a file. When you call methods like nextLine(), nextInt(), or next() and there is no more input available to read, Java throws NoSuchElementException. This is especially common when reading from files that end sooner than expected, or when a user closes the input stream.
The Broken Code:
java
import java.util.Scanner;
public class ScannerExample {
public static void main(String[] args) {
Scanner scanner = new Scanner("Hello");
System.out.println(scanner.nextLine()); // Works fine
System.out.println(scanner.nextLine()); // Throws NoSuchElementException
}
}
The Error:
Hello
Exception in thread "main" java.util.NoSuchElementException: No line found
at java.base/java.util.Scanner.nextLine(Scanner.java:1651)
at ScannerExample.main(ScannerExample.java:9)
The Fix:
Always check with hasNextLine() or hasNext() before reading from a scanner. These methods return false when there is nothing left to read, allowing you to stop reading gracefully before the exception has a chance to occur.
java
import java.util.Scanner;
public class ScannerExample {
public static void main(String[] args) {
Scanner scanner = new Scanner("Hello\nWorld");
while (scanner.hasNextLine()) {
System.out.println(scanner.nextLine());
}
scanner.close(); // Always close the scanner when done
}
}
Output:
Hello
World
When reading from files, the best practice is to wrap the scanner inside a try-with-resources block. This ensures the scanner is closed automatically even if an exception occurs during reading, which prevents resource leaks in your application.
java
import java.util.Scanner;
import java.io.File;
public class FileScannerExample {
public static void main(String[] args) throws Exception {
try (Scanner scanner = new Scanner(new File("data.txt"))) {
while (scanner.hasNextLine()) {
System.out.println(scanner.nextLine());
}
}
}
}
Optional.get() on an Empty Optional
Java 8 introduced the Optional class to help developers handle the absence of values more explicitly and to reduce NullPointerException occurrences. However, many developers replace one problem with another by calling .get() directly on an Optional without checking whether it actually contains a value. When the Optional is empty, this call throws NoSuchElementException.
The Broken Code:
java
import java.util.Optional;
public class OptionalExample {
public static void main(String[] args) {
Optional<String> name = Optional.empty();
// Throws NoSuchElementException because Optional is empty
System.out.println(name.get());
}
}
The Error:
Exception in thread "main" java.util.NoSuchElementException: No value present
at java.base/java.util.Optional.get(Optional.java:148)
at OptionalExample.main(OptionalExample.java:8)
Use isPresent() before get():
java
import java.util.Optional;
public class OptionalExample {
public static void main(String[] args) {
Optional<String> name = Optional.empty();
if (name.isPresent()) {
System.out.println(name.get());
} else {
System.out.println("Name is not available");
}
}
}
Use orElse() to provide a default value:
This is the cleanest and most recommended approach. If the Optional is empty, the fallback value is returned automatically without any conditional logic needed on your part.
java
import java.util.Optional;
public class OptionalExample {
public static void main(String[] args) {
Optional<String> name = Optional.empty();
String result = name.orElse("Default Name");
System.out.println(result); // Prints: Default Name
}
}
Use orElseThrow() with a meaningful exception:
When an empty Optional represents a genuinely exceptional situation in your business logic, you can throw a custom exception with a descriptive message instead of allowing the generic NoSuchElementException to propagate.
java
import java.util.Optional;
public class OptionalExample {
public static void main(String[] args) {
Optional<String> name = Optional.empty();
String result = name.orElseThrow(() ->
new IllegalArgumentException("User name must be present to continue")
);
}
}
Queue and Deque Operations on Empty Collection
Java’s Queue and Deque interfaces provide two versions of most operations. One version throws an exception when the operation cannot be completed, and the other version returns a special value such as null or false instead. Many developers unknowingly use the exception-throwing versions and are surprised when their application crashes on an empty queue.
The Broken Code:
java
import java.util.*;
public class QueueExample {
public static void main(String[] args) {
Queue<String> queue = new LinkedList<>();
// Both of these throw NoSuchElementException on an empty queue
System.out.println(queue.element());
System.out.println(queue.remove());
}
}
The Error:
Exception in thread "main" java.util.NoSuchElementException
at java.base/java.util.AbstractQueue.element(AbstractQueue.java:136)
at QueueExample.main(QueueExample.java:8)
The Fix:
Use peek() instead of element() and poll() instead of remove(). These are the safe alternatives that return null when the queue is empty rather than throwing an exception. Always check the return value of poll() and peek() before using it to avoid a NullPointerException downstream.
java
import java.util.*;
public class QueueExample {
public static void main(String[] args) {
Queue<String> queue = new LinkedList<>();
queue.add("First");
queue.add("Second");
// Safe operations that return null if queue is empty
String head = queue.peek(); // Looks at first element without removing it
String removed = queue.poll(); // Removes and returns the first element
System.out.println("Head: " + head);
System.out.println("Removed: " + removed);
// Always check before processing remaining elements
while (queue.peek() != null) {
System.out.println("Processing: " + queue.poll());
}
}
}
Output:
Head: First
Removed: First
Processing: Second
Stream findFirst() and findAny() Without Safe Handling
Stream terminal operations like findFirst() and findAny() do not return the value directly. They return an Optional wrapping the value. If no element matches the filter condition and the stream is empty, the returned Optional will be empty. Calling .get() on it at that point throws NoSuchElementException.
The Broken Code:
java
import java.util.*;
public class StreamExample {
public static void main(String[] args) {
List<String> names = Arrays.asList("Bob", "Charlie", "David");
// No name starts with "Z", so findFirst() returns an empty Optional
// Calling .get() on it throws NoSuchElementException
String result = names.stream()
.filter(name -> name.startsWith("Z"))
.findFirst()
.get();
System.out.println(result);
}
}
The Error:
Exception in thread "main" java.util.NoSuchElementException: No value present
at java.base/java.util.Optional.get(Optional.java:148)
at StreamExample.main(StreamExample.java:10)
The Fix:
Handle the Optional returned by findFirst() or findAny() using orElse(), orElseGet(), or orElseThrow() instead of calling .get() directly. The difference between orElse() and orElseGet() is that orElse() always evaluates its argument eagerly, while orElseGet() accepts a supplier and only evaluates it lazily when the Optional is actually empty, which is more efficient when the fallback value is expensive to compute.
java
import java.util.*;
public class StreamExample {
public static void main(String[] args) {
List<String> names = Arrays.asList("Bob", "Charlie", "David");
// Safe approach using orElse for a simple default value
String result = names.stream()
.filter(name -> name.startsWith("Z"))
.findFirst()
.orElse("No match found");
System.out.println(result); // Prints: No match found
// Use orElseGet when the fallback involves computation
String result2 = names.stream()
.filter(name -> name.startsWith("B"))
.findFirst()
.orElseGet(() -> "Computed fallback");
System.out.println(result2); // Prints: Bob
}
}
How to Catch No Such Element Exception Globally
There are situations where you cannot fully predict whether an element will be present, such as when working with third-party libraries or data sources outside your control. In those cases, wrapping the risky code in a try-catch block is a valid safety net. However, this should be a last resort, not a primary strategy.
java
import java.util.*;
public class CatchExample {
public static void main(String[] args) {
try {
List<String> list = new ArrayList<>();
Iterator<String> it = list.iterator();
System.out.println(it.next());
} catch (NoSuchElementException e) {
System.out.println("Caught exception: " + e.getMessage());
System.out.println("The collection was empty or fully exhausted.");
}
}
}
Using exceptions for flow control is considered bad practice in Java because exceptions are expensive to create and handle, and they make the code harder to read and maintain. Always prefer defensive checks like hasNext() or isPresent() over catching the exception after the fact.
Quick Reference
| Scenario | Unsafe Method | Safe Alternative |
|---|---|---|
| Iterator | next() without check | Check hasNext() first |
| Scanner | nextLine() without check | Check hasNextLine() first |
| Optional | .get() directly | Use orElse() or orElseThrow() |
| Queue | remove() and element() | Use poll() and peek() |
| Stream | findFirst().get() | Use findFirst().orElse() |