Quick answer
- Read the quoted value literally. The characters between the quotes are the exact input the parser choked on.
""= empty/missing upstream value." 42"= untrimmed whitespace (parseIntnever trims).- Looks valid but still fails? A hidden character — a BOM (
U+FEFF) or non-breaking space (U+00A0). Prints.length()and the char codes. "1,234"= grouping separator (useNumberFormat);"42.0"= decimal point (useDouble.parseDouble); a huge number =intoverflow (useLong.parseLong).
The exact error string
The stack trace names the parser and the offending value. The value in quotes is the whole story:
Exception in thread "main" java.lang.NumberFormatException: For input string: "1,234"
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.App.main(App.java:7)
You will also see these variants — same exception, different quoted content, and sometimes a trailing under radix N:
NumberFormatException: For input string: "" // empty string
NumberFormatException: For input string: " 42" // leading space (not trimmed)
NumberFormatException: For input string: "42.0" // decimal point, parsed as int
NumberFormatException: For input string: "null" // the literal text "null"
NumberFormatException: For input string: "12345678901" // overflows int range
NumberFormatException: For input string: "FF" under radix 10 // hex without radix 16
NumberFormatException: null // Integer.parseInt(null) — different message
The exception comes from Integer.parseInt, Long.parseLong, Double.parseDouble, new BigDecimal(...), or any similar parser that was handed a string it can't read as a number in the format it expects. Unlike many errors, this one hands you the failing input directly — so the fastest path to a fix is to decode what's between the quotes.
Anatomy of the message — the quotes are the input
The message is literally For input string: " + the exact CharSequence you passed + ". Whatever sits between those quotes is the raw value, character for character. The trap is that some of those characters are invisible: a trailing space shows as "42 " and is easy to miss, while a BOM or non-breaking space shows as nothing at all even though it's there. So the first move is always: copy the quoted content and look at what it actually contains.
This table maps the quoted value to its cause and fix — find your row:
| What's in the quotes | What it means | Fix |
|---|---|---|
"" (empty) | Missing upstream value — blank field, absent JSON key | Check empty/null first; supply a default |
" 42" / "42\n" | Whitespace; parseInt does not trim | s.trim() (or strip()) before parsing |
Looks like "42" but fails | Hidden char — BOM U+FEFF or NBSP U+00A0 | Print length + char codes; strip the char |
"1,234" / "1.234" | Thousands/grouping separator (locale) | Use NumberFormat, or remove separators |
"42.0" / "3.14" | Decimal point given to an integer parser | Use Double.parseDouble / BigDecimal |
"12345678901" | Value exceeds int range (±2.1 billion) | Use Long.parseLong / BigInteger |
"null" / "undefined" | A null/undefined got stringified upstream | Fix the source; treat as missing |
"0x1F" / "FF" | Non-decimal digits with the default radix 10 | parseInt(s, 16) or Integer.decode |
Fix 1: trim first — parseInt does not
A surprising number of these are just whitespace. Integer.parseInt accepts only an optional sign and digits; a single leading or trailing space fails it. Values pulled from a file, a form, or a split CSV column routinely carry them:
Integer.parseInt(" 42"); // throws: For input string: " 42"
Integer.parseInt("42 "); // throws: For input string: "42 "
Integer.parseInt(" 42".trim()); // 42 (Java: trim removes ASCII whitespace)
Integer.parseInt(" 42 ".strip()); // 42 (Java 11+: strip is Unicode-aware, also removes NBSP-like spaces)
Prefer strip() on Java 11+ — it's Unicode-aware and removes several space characters that trim() leaves behind, which is exactly what you want when the culprit is a stray non-breaking space.
Fix 2: a value that "looks fine" — find the hidden character
When the quoted value looks like a perfectly good number and still fails, there is an invisible character in it. The two usual offenders are the byte-order mark (U+FEFF, code 65279) at the start of a UTF-8 file's first field, and a non-breaking space (U+00A0, code 160) from data copied out of a web page or spreadsheet. Prove it by printing the length and the code points:
String s = readFirstColumn(); // looks like "42" in the console
System.out.println(s.length()); // 3 <- one char too many!
s.chars().forEach(c -> System.out.printf("%d ", c));
// 65279 52 50 <- a BOM (65279) is hiding in front of '4' '2'
// strip anything that isn't a digit or sign, then parse
int n = Integer.parseInt(s.replaceAll("[^0-9-]", "")); // 42
If this value came from a JSON payload or an API response, inspect the raw body before you parse anything — paste it into the JSON Formatter to see the exact bytes and confirm whether the number arrived as a proper JSON number or as a quoted string with junk around it. A field that should be {"qty": 42} but is actually {"qty": " 42"} is the whole bug, visible at a glance.
Fix 3: grouping separators and locale (the comma)
Integer.parseInt has no concept of a thousands separator, so "1,234" throws. Either strip the separators, or — if the input is genuinely locale-formatted — parse it with a locale-aware NumberFormat:
import java.text.NumberFormat;
import java.util.Locale;
// locale-aware parse (throws java.text.ParseException, NOT NumberFormatException)
NumberFormat nf = NumberFormat.getInstance(Locale.US);
int n = nf.parse("1,234").intValue(); // 1234
// or just remove the grouping character before parseInt
int m = Integer.parseInt("1,234".replace(",", "")); // 1234
Two gotchas with NumberFormat.parse: it throws java.text.ParseException rather than NumberFormatException, and it is lenient — it parses as far as it can and stops, so "12abc" returns 12 instead of failing. If you need strict all-or-nothing parsing, validate the string first or stick with parseInt on a cleaned value.
Fix 4: decimal points, overflow, and radix
Three more mismatches between the value and the parser you chose:
- Decimal point —
Integer.parseInt("42.0")throws because anintparser rejects the.. UseDouble.parseDouble("42.0"), ornew BigDecimal("42.0")for exact decimal money math. - Overflow —
Integer.parseInt("12345678901")throws because the value is larger thanInteger.MAX_VALUE(about 2.1 billion). The digits are all valid; there are just too many. UseLong.parseLong, orBigIntegerfor arbitrary size. - Wrong radix —
Integer.parseInt("FF")throwsunder radix 10because hex digits aren't decimal. Pass the radix:Integer.parseInt("FF", 16)returns 255. For a0x-prefixed literal useInteger.decode("0x1F").
double d = Double.parseDouble("42.0"); // 42.0
long l = Long.parseLong("12345678901"); // 12345678901
int h = Integer.parseInt("FF", 16); // 255
int x = Integer.decode("0x1F"); // 31
Fix 5: parse defensively at trust boundaries
When the number comes from anything you don't control — a form field, a query parameter, an uploaded file, a JSON body — a bad value is a user problem, not a server crash. Don't let NumberFormatException bubble up into a 500. Validate or catch, and return a clean error:
static int parseQuantity(String raw) {
if (raw == null || raw.isBlank()) {
throw new IllegalArgumentException("quantity is required");
}
String s = raw.strip();
if (!s.matches("-?\\d+")) { // shape-check before parsing
throw new IllegalArgumentException("quantity must be a whole number, got: " + s);
}
try {
return Integer.parseInt(s);
} catch (NumberFormatException e) { // still possible: overflow
throw new IllegalArgumentException("quantity is too large: " + s);
}
}
The regex rejects empty strings, decimals, and stray characters up front with a message that names the actual value, and the catch still handles the one case a shape-check can't — a well-formed run of digits that overflows int. This turns a stack trace into a validation message a caller can act on. It's the numeric cousin of guarding against a NullPointerException before you dereference.
Debugging checklist
- ✓ Read the exact value between the quotes — it's the literal input that failed
- ✓ Empty (
"")? An upstream value was missing — check for blank/null first - ✓ Whitespace (
" 42")?parseIntdoesn't trim —strip()before parsing - ✓ Looks valid but fails? Print
s.length()+ char codes; strip a BOM (65279) or NBSP (160) - ✓ Comma/dot separator? Use
NumberFormator remove the grouping char - ✓ Decimal point? Use
Double.parseDouble/BigDecimal, notparseInt - ✓ Huge number? Use
Long.parseLong/BigInteger— it overflowedint - ✓ From a request/file/JSON? Validate and catch — never let it become a 500
Frequently Asked Questions
What does NumberFormatException: For input string mean?
A parser like Integer.parseInt, Long.parseLong, or Double.parseDouble was given a string that is not a valid number in the expected format. The exact characters between the quotes in the message are the literal input it tried to parse. Read them carefully — the value that failed is right there, including any whitespace or hidden characters.
Why does 'For input string: ""' happen with an empty string?
The input was an empty string. Integer.parseInt("") throws because there are no digits to parse. This usually means an upstream value was missing — an empty form field, an absent JSON property that arrived as "", or a config key with no value. Check for empty and null before parsing and supply a default.
Why does Integer.parseInt fail on a value that looks like a valid number?
There is almost always an invisible character. Integer.parseInt does not trim, so leading or trailing spaces fail. A copied value can also carry a byte-order mark (U+FEFF) or a non-breaking space (U+00A0) that renders as nothing. Print s.length() and the character codes — a "42" of length 3, or one containing code 65279 or 160, confirms a hidden character.
How do I parse a number with a comma like '1,234'?
Integer.parseInt does not understand grouping separators, so "1,234" fails. Strip the separators first, or use a locale-aware NumberFormat: NumberFormat.getInstance(Locale.US).parse("1,234").intValue() returns 1234. Note NumberFormat.parse throws java.text.ParseException, not NumberFormatException, and it stops at the first non-numeric character rather than rejecting the whole string.
Why does Integer.parseInt fail on '42.0'?
Integer.parseInt only accepts an optional sign and digits — no decimal point. "42.0" is a floating-point literal, so it throws. Use Double.parseDouble("42.0") for a double, or if you truly want an int, parse as a double and round or truncate, or split on the decimal point after validating the shape.
How do I parse safely without throwing NumberFormatException?
Trim and validate first, then parse inside a try/catch that returns a default on failure, or check the string against a regex like ^-?\d+$ before calling parseInt. Never let a NumberFormatException from untrusted input (a form, an API, a file) crash a request — catch it and return a clean validation error instead.
Inspect the payload, then fix the parse
When the number arrives inside JSON, look at the raw body first — then browse the full error reference.