Java NumberFormatException — String cannot be parsed as a number
NumberFormatException: invalid numeric string
Verified against OpenJDK 21 documentation, Java SE API docs Integer.parseInt, JLS §4.2 · Updated June 2026
> quick_fix
Wrap the parse call in a try-catch or validate the string with a regex/null check before calling Integer.parseInt(). For optional numeric input, provide a default value on failure.
// Safe parse with try-catch
public static int parseIntSafe(String s, int defaultValue) {
try {
return Integer.parseInt(s);
} catch (NumberFormatException e) {
return defaultValue;
}
}
// Usage
int value = parseIntSafe(request.getParameter("count"), 0);
// Java 8+: using Optional
Optional<Integer> parsed = Optional.ofNullable(s)
.filter(str -> str.matches("-?\\d+"))
.map(Integer::parseInt);What causes this error
NumberFormatException is thrown by Integer.parseInt(), Long.parseLong(), Double.parseDouble(), and similar methods when the input string is null, empty, contains non-numeric characters, has leading/trailing whitespace, or represents a value outside the numeric type's range.
How to fix it
- 01
step 1
Check the input string value
Log the string just before the parse call: `System.out.println("Parsing: '" + s + "'")`. Common culprits are empty strings (""), whitespace (" 42"), commas in large numbers ("1,000"), currency symbols ("$99"), or the literal string "null".
- 02
step 2
Trim whitespace before parsing
User input and query parameters often carry leading or trailing spaces. Always call `.trim()` before parsing: `Integer.parseInt(s.trim())`. This handles the most common form-input NumberFormatException.
- 03
step 3
Validate with a regex or isEmpty check
Before parsing, check the string is not null or empty: `if (s == null || s.isBlank()) return defaultValue;`. For integers: `s.matches("-?\\d+")`. For decimals: `s.matches("-?\\d+(\\.\\d+)?")`. Validate before, not after.
- 04
step 4
Handle locale-specific number formats
Strings like "1,234.56" or "1.234,56" (European format) cannot be parsed by Double.parseDouble(). Use NumberFormat or DecimalFormat with the appropriate Locale: `NumberFormat.getInstance(Locale.GERMANY).parse(s)`.
- 05
step 5
Use the right type for the value's range
Integer.parseInt() fails if the number is larger than Integer.MAX_VALUE (2,147,483,647). Use Long.parseLong() for larger values. For arbitrary precision, use new BigDecimal(s) which accepts any numeric string.
How to verify the fix
- Test with edge-case inputs: null, empty string, whitespace-only, letters mixed in, very large numbers
- Confirm that the default/fallback value is applied when invalid input is supplied
- Check logs — no uncaught NumberFormatException stack traces
Why NumberFormatException happens at the runtime level
Integer.parseInt() and related methods implement a strict character-by-character parser that accepts only an optional leading minus sign followed by ASCII digits. Any deviation — whitespace, commas, decimal points, currency symbols, or a string that is null or empty — causes the method to throw NumberFormatException. The method does not perform locale-aware parsing; that responsibility is delegated to the NumberFormat/DecimalFormat family. This strict design is intentional to keep the core parse methods fast and predictable.
Common debug mistakes for NumberFormatException
- Not calling .trim() on user input before parsing — a space before the number is invisible in logs
- Parsing query parameters directly without a null/empty check — missing parameters return null from getParameter()
- Using Integer.parseInt() for values that can exceed 2.1 billion (Unix timestamps, IDs from large databases)
- Parsing formatted currency or percentage strings ("₹1,299", "45%") without stripping non-numeric characters first
When NumberFormatException signals a deeper problem
NumberFormatException at runtime is almost always an input validation gap — the application accepts external string data and converts it to a number without defending against malformed input. The systemic fix is to validate and coerce at the boundary (controller/DTO layer) before the value enters the domain model, using a consistent parse utility that returns a default or throws a meaningful domain exception rather than exposing the raw NumberFormatException to upper layers.
Editor's take
NumberFormatException in Java fires when you pass a string to `Integer.parseInt()`, `Double.parseDouble()`, or similar methods and the string cannot be interpreted as the target numeric type. It's one of the most frequently encountered exceptions in web backends because user input from HTTP parameters, form fields, and CSV imports is always a string — and users submit surprisingly creative non-numeric content. The production-grade pattern is to never use `parseInt()` directly on untrusted input without wrapping it in a try-catch or using a validation library first. In Spring Boot applications, the framework's `@RequestParam` binding handles this automatically and returns a 400 Bad Request, but if you're parsing manually in service layers, the exception propagates as an unhandled 500. Common gotchas: leading/trailing whitespace (use `.trim()` first), locale-specific thousands separators (German uses dots: "1.234"), hex strings without the `0x` prefix, and numeric strings that exceed `Integer.MAX_VALUE` but would fit in a `Long`. Since Java 9, `Optional`-returning parse methods haven't materialized in the standard library, but Apache Commons `NumberUtils.toInt(str, defaultValue)` provides a clean fallback pattern. Understanding where NumberFormatException fires is essentially understanding the boundary between string-typed external data and your application's internal numeric types.
By Bikram Nath · Curator · Updated June 2026
Frequently asked questions
Why does Integer.parseInt("1,000") throw NumberFormatException?
parseInt() does not understand locale-specific grouping separators. You must strip commas first: `s.replace(",", "")`, or use NumberFormat.getInstance(Locale.US).parse(s) which handles the grouping separator properly.
Is NumberFormatException checked or unchecked?
It is unchecked (extends IllegalArgumentException, which extends RuntimeException). You are not required to catch it at compile time, but you should handle it whenever parsing user-supplied or external data.
How do I parse a hex string in Java?
Use Integer.parseInt(s, 16) for hexadecimal. The string must not have a '0x' prefix — strip it first if present: `Integer.parseInt(s.startsWith("0x") ? s.substring(2) : s, 16)`.