TL;DRYou called Integer.parseInt() โ or something like it โ on a string that isn't a valid number. An empty string, a word, a value like "1,000", or even a stray space will all blow up with this error. Wrap the call in a try-catch, or validate first.
// Quick fix โ wrap with try-catch
try {
int value = Integer.parseInt(input);
} catch (NumberFormatException e) {
System.err.println("Invalid number: " + input);
// handle default, return error, etc.
}
What triggers this errorThe full stack trace looks like this:
Exception in thread "main" java.lang.NumberFormatException: For input string: "abc"
at java.base/java.lang.NumberFormatException.forInputString(NumberFormatException.java:67)
at java.base/java.lang.Integer.parseInt(Integer.java:668)
at java.base/java.lang.Integer.parseInt(Integer.java:786)
at com.example.Main.main(Main.java:8)
Java's parsing methods are strict. They accept only digit characters, with an optional leading - or +. That's it. Anything else throws NumberFormatException. The most common culprits:
- Unvalidated user input (
"abc","",null)- Numbers with thousands separators:"1,000"- Numbers with units appended:"42px","5MB"- Floating-point strings passed toparseInt:"3.14"- Strings with leading or trailing whitespace:" 7 "- Values read from CSV, JSON, or a database column that turned out to benullor malformed## Fix approaches### 1. Try-catch (most common)This is the bread-and-butter solution. Reach for it when you need to tell apart a bad value from a missing one โ or when you want a log entry showing exactly what string caused the problem.
public static Integer safeParseInt(String s) {
try {
return Integer.parseInt(s);
} catch (NumberFormatException e) {
return null; // or a default like 0
}
}
// Usage
Integer age = safeParseInt(request.getParameter("age"));
if (age == null) {
throw new IllegalArgumentException("age must be a number");
}
2. Trim whitespace before parsingA stray space is one of the sneakiest causes of this error โ especially with values read from files or form fields. One call to .trim() often saves the day.
int value = Integer.parseInt(input.trim());
3. Validate with a regex firstReject bad input at the gate. This approach gives you a clear, early error message instead of a cryptic exception buried in a stack trace.
if (!input.matches("-?\\d+")) {
throw new IllegalArgumentException("Expected an integer, got: " + input);
}
int value = Integer.parseInt(input);
4. Handle locale-formatted numbers (1,000 / 1.000)parseInt has no concept of locales โ "1,234,567" will always fail. Switch to NumberFormat when reading numbers formatted for a specific region.
import java.text.NumberFormat;
import java.util.Locale;
String formatted = "1,234,567";
NumberFormat nf = NumberFormat.getInstance(Locale.US);
long value = nf.parse(formatted).longValue(); // 1234567
5. Parse decimals masquerading as integersGot "3.14" but need a plain int? Parse as double first, then cast. You'll get 3 โ the fractional part is dropped, not rounded.
String s = "3.14";
int value = (int) Double.parseDouble(s); // 3
6. Apache Commons Lang (optional utility)Already pulling in Commons Lang? NumberUtils handles null, empty strings, and bad input without throwing โ no try-catch boilerplate needed.
import org.apache.commons.lang3.math.NumberUtils;
int value = NumberUtils.toInt("abc", 0); // returns 0 (default)
boolean valid = NumberUtils.isCreatable("123"); // true
7. Java 8+ Optional patternPrefer functional pipelines? Return an OptionalInt instead of throwing or returning null. It makes the absence of a value explicit โ no silent defaults hiding in your code.
import java.util.OptionalInt;
public static OptionalInt tryParseInt(String s) {
if (s == null || s.isBlank()) return OptionalInt.empty();
try {
return OptionalInt.of(Integer.parseInt(s.trim()));
} catch (NumberFormatException e) {
return OptionalInt.empty();
}
}
// Usage
tryParseInt(input).ifPresentOrElse(
val -> System.out.println("Parsed: " + val),
() -> System.out.println("Not a valid integer")
);
Edge cases to watch- Null input โ Integer.parseInt(null) throws NumberFormatException, not an NPE. Surprising, but true. Always null-check before calling parse.- Integer overflow โ "99999999999" exceeds Integer.MAX_VALUE (2,147,483,647) and will throw. Use Long.parseLong() or new BigInteger(s) for big values.- Hex strings โ "0xFF" fails with plain parseInt. Use Integer.parseInt(s.substring(2), 16) or the cleaner Integer.decode("0xFF").- Scientific notation โ "1e5" isn't a valid integer string. Parse it as Double first, then cast.## Verifying the fixRun these assertions against your parsing utility. All the awkward edge cases are covered โ if every line passes, you're good to ship.
// Basic valid input
assert safeParseInt("42") != null;
assert safeParseInt("-7") != null;
assert safeParseInt(" 10 ") != null; // after trim
// Should return null / default โ not throw
assert safeParseInt("") == null;
assert safeParseInt("abc") == null;
assert safeParseInt(null) == null;
assert safeParseInt("3.14") == null;
assert safeParseInt("1,000") == null; // unless you strip commas first
System.out.println("All checks passed");
No exceptions, output reads All checks passed? The fix holds.

