elastic/elasticsearch · error · ParseException

expected ( but found: {}

Error message

expected ( but found: {}

What it means

Thrown by WellKnownText.nextOpener when the token at the current position is not '('. This helper asserts an opening parenthesis, used when descending into a nested sub-structure (e.g., a second-level group in a MultiPolygon or the inner ring group of a Polygon).

Source

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

    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);
        if (token.equals(COMMA) || token.equals(RPAREN)) {
            return token;
        }
        throw new ParseException("expected " + COMMA + " or " + RPAREN + " but found: " + tokenString(stream), stream.lineno());
    }

    private static String getWKTName(Geometry geometry) {
        return geometry.visit(new GeometryVisitor<String, RuntimeException>() {
            @Override
            public String visit(Circle circle) {
                return "CIRCLE";
            }

            @Override

View on GitHub (pinned to db6a809a66)

Solutions

  1. Add the missing '(' to open the expected sub-group, matching the nesting grammar of the geometry type.
  2. Cross-check against a reference WKT example for the type (e.g., MULTIPOINT, MULTIPOLYGON, GEOMETRYCOLLECTION) to confirm nesting depth.

Example fix

// before: missing inner open paren for polygon in multipolygon
Geometry g = WellKnownText.fromWKT("MULTIPOLYGON ((0 0, 1 0, 1 1, 0 0))");

// after: correct nesting — polygon ring wrapped in its own parens
Geometry g = WellKnownText.fromWKT("MULTIPOLYGON (((0 0, 1 0, 1 1, 0 0)))");
Defensive patterns

Strategy: try-catch

Try / catch

try {
    Geometry g = WellKnownText.fromWKT(wkt);
} catch (java.text.ParseException e) {
    if (e.getMessage().contains("expected (")) {
        // missing nested open paren; check geometry-type nesting grammar
    }
    throw e;
}

Prevention

When it happens

Trigger: WKT where a nested '(' is expected but missing. For example, in a MultiPolygon each polygon is wrapped in its own parens: "MULTIPOLYGON (((0 0, ...)))". If an inner '(' is omitted, nextOpener throws.

Common situations: Malformed multi-geometry WKT with insufficient nesting levels; hand-authored WKT missing a paren level; conversion bug that flattens nested structures.

Related errors


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