elastic/elasticsearch · error · ParseException

expected ) but found: {}

Error message

expected ) but found: {}

What it means

Thrown by WellKnownText.nextCloser when the token following a coordinate sequence is not ')'. This helper asserts the closing parenthesis that terminates a geometry's parenthesized body.

Source

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

        } catch (ParseException | IOException e) {
            return false;
        }

    }

    static String nextEmptyOrOpen(StreamTokenizer stream) throws IOException, ParseException {
        final String next = nextWord(stream);
        if (next.equals(EMPTY) || next.equals(LPAREN)) {
            return next;
        }
        throw new ParseException("expected " + EMPTY + " or " + LPAREN + " but found: " + tokenString(stream), stream.lineno());
    }

    static String nextCloser(StreamTokenizer stream) throws IOException, ParseException {
        if (nextWord(stream).equals(RPAREN)) {
            return RPAREN;
        }
        throw new ParseException("expected " + RPAREN + " but found: " + tokenString(stream), stream.lineno());
    }

    static String nextComma(StreamTokenizer stream) throws IOException, ParseException {
        if (nextWord(stream).equals(COMMA)) {
            return COMMA;
        }
        throw new ParseException("expected " + COMMA + " but found: " + tokenString(stream), stream.lineno());
    }

    static String nextOpener(StreamTokenizer stream) throws IOException, ParseException {
        if (nextWord(stream).equals(LPAREN)) {
            return LPAREN;
        }
        throw new ParseException("expected " + LPAREN + " but found: " + tokenString(stream), stream.lineno());
    }

    static String nextCloserOrComma(StreamTokenizer stream) throws IOException, ParseException {
        String token = nextWord(stream);

View on GitHub (pinned to db6a809a66)

Solutions

  1. Ensure every '(' has a matching ')' and no stray tokens sit between the last coordinate and the closer.
  2. Validate paren balance in the WKT string before parsing.

Example fix

// before: missing closing paren
Geometry g = WellKnownText.fromWKT("POINT (1 2");

// after: balanced parens
Geometry g = WellKnownText.fromWKT("POINT (1 2)");
Defensive patterns

Strategy: validation

Validate before calling

// Verify parenthesis balance
static void checkParenBalance(String wkt) {
    int depth = 0;
    for (int i = 0; i < wkt.length(); i++) {
        char c = wkt.charAt(i);
        if (c == '(') depth++;
        else if (c == ')') depth--;
        if (depth < 0) throw new IllegalArgumentException("unbalanced ')' in WKT");
    }
    if (depth != 0) throw new IllegalArgumentException("unbalanced '(' in WKT");
}

Try / catch

try {
    Geometry g = WellKnownText.fromWKT(wkt);
} catch (java.text.ParseException e) {
    if (e.getMessage().contains("expected )")) {
        // missing closing paren
    }
    throw e;
}

Prevention

When it happens

Trigger: WKT where a closing ')' is missing or replaced, e.g. "POINT (1 2," (trailing comma then EOF), "POINT (1 2 3" (no closer), or "POINT (1 2]" (wrong bracket). After reading the last coordinate, nextCloser expects ')' but finds something else.

Common situations: Truncated WKT missing the final ')'; wrong bracket type from a non-WKT source; an extra token after the last coordinate.

Related errors


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