elastic/elasticsearch · error · ParseException

invalid number found: {}

Error message

invalid number found: {}

What it means

Thrown by WellKnownText.nextNumber when the StreamTokenizer yields a TT_WORD that is neither the literal NAN nor parseable by Double.parseDouble. The tokenizer delivered a word-like token where a numeric coordinate was expected, but the word is not a valid floating-point literal.

Source

Thrown at libs/geo/src/main/java/org/elasticsearch/geometry/utils/WellKnownText.java:708

            case '(':
                return LPAREN;
            case ')':
                return RPAREN;
            case ',':
                return COMMA;
        }
        throw new ParseException("expected word but found: " + tokenString(stream), stream.lineno());
    }

    static double nextNumber(StreamTokenizer stream) throws IOException, ParseException {
        if (stream.nextToken() == StreamTokenizer.TT_WORD) {
            if (stream.sval.equalsIgnoreCase(NAN)) {
                return Double.NaN;
            } else {
                try {
                    return Double.parseDouble(stream.sval);
                } catch (NumberFormatException e) {
                    throw new ParseException("invalid number found: " + stream.sval, stream.lineno());
                }
            }
        }
        throw new ParseException("expected number but found: " + tokenString(stream), stream.lineno());
    }

    static String tokenString(StreamTokenizer stream) {
        return switch (stream.ttype) {
            case StreamTokenizer.TT_WORD -> stream.sval;
            case StreamTokenizer.TT_EOF -> EOF;
            case StreamTokenizer.TT_EOL -> EOL;
            case StreamTokenizer.TT_NUMBER -> NUMBER;
            default -> "'" + (char) stream.ttype + "'";
        };
    }

    static boolean isNumberNext(StreamTokenizer stream) throws IOException {
        final int type = stream.nextToken();

View on GitHub (pinned to db6a809a66)

Solutions

  1. Inspect the coordinate token reported (stream.sval) and correct the source data to be a valid double literal or the keyword NAN.
  2. If locale formatting is the cause, normalize decimal separators to '.' upstream.
  3. Validate coordinate fields as numeric before generating WKT.

Example fix

// before: non-numeric coordinate token
Geometry g = WellKnownText.fromWKT("POINT (abc 2)");

// after: valid numeric literal
Geometry g = WellKnownText.fromWKT("POINT (1.5 2)");
// or the special NAN keyword if intended
Geometry g = WellKnownText.fromWKT("POINT (NAN 2)");
Defensive patterns

Strategy: validation

Validate before calling

// Pre-check coordinate tokens are numeric or NAN
static boolean isValidCoordinateToken(String tok) {
    if (tok.equalsIgnoreCase("NAN")) return true;
    try { Double.parseDouble(tok); return true; }
    catch (NumberFormatException e) { return false; }
}

Try / catch

try {
    Geometry g = WellKnownText.fromWKT(wkt);
} catch (java.text.ParseException e) {
    if (e.getMessage().startsWith("invalid number")) {
        // surface the offending token to the user
    }
    throw e;
}

Prevention

When it happens

Trigger: A coordinate position in WKT containing a word that is not 'NAN' and not a number, e.g. "POINT (abc 2)" or "POINT (1.x 2)". The tokenizer treats 'abc' as a word; nextNumber sees TT_WORD, fails Double.parseDouble, and throws.

Common situations: Corrupt coordinate data; locale-specific decimal separators (comma vs period) confusing the tokenizer; placeholder tokens like 'NULL' or 'INF' that are not the expected 'NAN'; a field-mapping bug feeding a label into a coordinate slot.

Related errors


AI-assisted analysis of elastic/elasticsearch@db6a809a66 (2026-08-12). Data as JSON: /api/errors/1e3640df73bc4d50. Report an issue: GitHub.