Java NumberFormatException — Unparseable Numeric String
Fix NumberFormatException by trimming input, matching the radix to Integer.parseInt, and using the correct parse method for decimals and large numbers.
Symptoms
- java.lang.NumberFormatException: For input string: "12a"
- Parsing works for small numbers but fails on large or decimal values
- A form value with spaces cannot be converted
Possible causes
- The string contains non-digit characters or surrounding whitespace
- A decimal or scientific notation is parsed with parseInt instead of parseDouble
- A value exceeds the range of int and needs long or BigInteger
Diagnosis steps
Reproduce and read the offending string
jshell -q <<'EOF'
try { Integer.parseInt(" 12 "); } catch (NumberFormatException e) { System.out.println(e.getMessage()); }
EOFInterpretation
The message includes the exact string, exposing whitespace or stray characters.
Choose the right parse method
Double.parseDouble("3.14"); Long.parseLong("9000000000");Interpretation
parseDouble handles decimals, parseLong handles values beyond int range.
Root cause
The parse methods accept only an optional sign and digits for the requested radix, with no leading or trailing whitespace. Anything else, including a decimal point for parseInt, throws NumberFormatException.
Fix
Trim and validate input, use Integer.parseInt with the correct radix, Double.parseDouble for decimals, Long.parseLong/BigInteger for large values, and NumberFormat for locale-formatted input.
Risk note
Locale-formatted numbers with commas need NumberFormat; parseInt rejects them even after trim.
Verify the fix
Rerun with the original input and confirm a correct value or a controlled validation error; add tests for whitespace, decimals, and overflow.
Symptoms
This debugging guide addresses “Java NumberFormatException — Unparseable Numeric String”. Start from the symptoms, follow the ordered diagnostics, and confirm each hypothesis before moving on; the fix and verification steps then close the loop.
Observed symptoms include:
- java.lang.NumberFormatException: For input string: “12a”
- Parsing works for small numbers but fails on large or decimal values
- A form value with spaces cannot be converted
Reproduce and Diagnose
Reproduce the failure in isolation before changing any code. Work through the checks below in order; each one narrows the search space.
Step 1: Reproduce and read the offending string
jshell -q <<'EOF'
try { Integer.parseInt(" 12 "); } catch (NumberFormatException e) { System.out.println(e.getMessage()); }
EOF
The message includes the exact string, exposing whitespace or stray characters.
Step 2: Choose the right parse method
Double.parseDouble("3.14"); Long.parseLong("9000000000");
parseDouble handles decimals, parseLong handles values beyond int range.
Likely contributors, in order of frequency:
- The string contains non-digit characters or surrounding whitespace
- A decimal or scientific notation is parsed with parseInt instead of parseDouble
- A value exceeds the range of int and needs long or BigInteger
Root Cause
The parse methods accept only an optional sign and digits for the requested radix, with no leading or trailing whitespace. Anything else, including a decimal point for parseInt, throws NumberFormatException.
The Fix
Trim and validate input, use Integer.parseInt with the correct radix, Double.parseDouble for decimals, Long.parseLong/BigInteger for large values, and NumberFormat for locale-formatted input.
Watch out: Locale-formatted numbers with commas need NumberFormat; parseInt rejects them even after trim.
public static int safeInt(String raw) {
if (raw == null) throw new IllegalArgumentException("null input");
String s = raw.trim();
if (!s.matches("[+-]?\\d+")) {
throw new IllegalArgumentException("not an integer: " + raw);
}
try {
return Integer.parseInt(s);
} catch (NumberFormatException e) {
return Math.toIntExact(Long.parseLong(s)); // precise overflow error
}
}
Verify and Prevent
Rerun with the original input and confirm a correct value or a controlled validation error; add tests for whitespace, decimals, and overflow.
Once verified, add a regression test that reproduces the original symptom so the failure cannot silently return.
This class of failure is usually environmental rather than pure logic, so capture the exact command, the environment variables, and the working directory in your bug report. Reproduce it in the smallest possible script, then widen the scope only once the minimal case is understood. A short written checklist for this failure mode saves hours the next time it appears.