🔴 The Error You're Seeing
Confirm this matches your console output. If it does, you're in the right place.
java.util.NoSuchElementException: No line found
at java.base/java.util.Scanner.nextLine(Scanner.java:1690)⚡ Quick Fix Works 80% of the time
Check hasNextLine() before every nextLine() call.
if (scanner.hasNextLine()) {
String line = scanner.nextLine();
handle(line);
}🧠 Why this Happens
Tap to expand the deep technical explanation
Scanner buffers chunks of its source and scans ahead looking for line terminators. At end of input there is no terminator left, so nextLine() cannot honor its contract of returning a line minus terminator and calls Scanner.throwFor, raising NoSuchElementException with detail "No line found". If the underlying stream was closed earlier you get a plain message-less NoSuchElementException instead: different wording, same root cause of reading past a dead source.
The HITEC City Parking Spot Analogy:
Pressing the button on a vending machine after it sold out: the mechanism still works, but inventory is zero.
🔁 How to Reproduce Confirm this is your error
Scanner sc = new Scanner(""); sc.nextLine(); // throws immediately - the input has zero lines
🛠️ Solutions (5 Ways to Fix)
Guard with hasNextLine()
👉 Use this if you must keep streaming reads from a Scanner.
hasNextLine() blocks until a line is available or EOF is confirmed, letting the loop exit normally instead of throwing mid-read.
while (scanner.hasNextLine()) {
parse(scanner.nextLine());
}Read the whole input once, then index safely
👉 Use this if the input fits memory and multiple passes or random access are needed.
Files.readAllLines returns a List whose size you can check; missing records become index/logic errors you control rather than scanner exceptions.
List<String> lines = Files.readAllLines(Path.of("input.txt"));
for (int i = 0; i < lines.size(); i++) {
parse(i, lines.get(i));
}Never close a shared Scanner(System.in)
👉 Use this if several classes read console input in one application.
Closing a Scanner closes its underlying System.in for the entire process; every later read then fails instantly. Own one Scanner per stream and close nothing until shutdown.
public class ConsoleIO {
private static final Scanner IN = new Scanner(System.in);
public static String ask(String prompt) {
System.out.print(prompt);
return IN.hasNextLine() ? IN.nextLine() : "";
}
}Switch to BufferedReader.readLine()
👉 Use this if you prefer an end-of-file convention over exceptions.
BufferedReader signals EOF by returning null, so the classic while ((line = br.readLine()) != null) loop never throws on exhaustion.
try (BufferedReader br = Files.newBufferedReader(path)) {
String line;
while ((line = br.readLine()) != null) {
parse(line);
}
}Validate record counts for fixed-format files
👉 Use this if the format promises a known number of records.
Read everything, compare against the expected count, and fail fast with a message naming the file and counts instead of crashing halfway through parsing.
List<String> rows = Files.readAllLines(csv);
if (rows.size() != EXPECTED_ROWS) {
throw new IllegalStateException("expected " + EXPECTED_ROWS
+ " rows, got " + rows.size());
}📋 Version Notes
Same wording and behavior.
Unchanged. Note: after nextInt() a following nextLine() returns the empty string because the pending newline counts as a line - that produces skipped-input bugs rather than this exception.
🛡️ How to Prevent This Next Time
Pair every next*() call with its hasNext*() twin. Give one component ownership of each input stream and let try-with-resources close it exactly once.