{"record":{"id":"1964477155c7ca20","repo":"elastic/elasticsearch","slug":"max-x-cannot-be-less-than-min-x","errorCode":null,"errorMessage":"max x cannot be less than min x","messagePattern":"max x cannot be less than min x","errorType":"validation","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"libs/geo/src/main/java/org/elasticsearch/geometry/utils/CartesianValidator.java","lineNumber":44,"sourceCode":" * Validator for cartesian (non-geographic) coordinates. Its one job today is\n * {@link #validateBBox(double, double, double, double)}: unlike geographic coordinates, cartesian coordinates\n * have no antimeridian-crossing concept, so a rectangle's x-ordinates must be consistent (maxX cannot be less\n * than minX), in addition to the same y-ordinate check ({@link GeographyValidator} also applies to geographic\n * coordinates. This is deliberately a separate class from {@link StandardValidator}, even though the two\n * currently look similar in scope: {@link StandardValidator} is CRS-agnostic and is relied on by real\n * geographic production code paths (e.g. {@code GeometryParser}) that must tolerate antimeridian-crossing\n * envelopes, so it cannot safely gain this check.\n */\npublic class CartesianValidator implements GeometryValidator {\n\n    public static final GeometryValidator INSTANCE = new CartesianValidator();\n\n    private CartesianValidator() {}\n\n    @Override\n    public void validateBBox(double minX, double maxX, double maxY, double minY) {\n        if (maxX < minX) {\n            throw new IllegalArgumentException(\"max x cannot be less than min x\");\n        }\n        GeometryValidator.super.validateBBox(minX, maxX, maxY, minY);\n    }\n\n    @Override\n    public void validate(Geometry geometry) {\n        geometry.visit(new GeometryVisitor<Void, RuntimeException>() {\n\n            @Override\n            public Void visit(Circle circle) throws RuntimeException {\n                return null;\n            }\n\n            @Override\n            public Void visit(GeometryCollection<?> collection) throws RuntimeException {\n                for (Geometry g : collection) {\n                    g.visit(this);\n                }","sourceCodeStart":26,"sourceCodeEnd":62,"githubUrl":"https://github.com/elastic/elasticsearch/blob/db6a809a667c081ca1dc7500389d26975573215f/libs/geo/src/main/java/org/elasticsearch/geometry/utils/CartesianValidator.java#L26-L62","documentation":"Thrown by CartesianValidator.validateBBox when maxX < minX. Cartesian coordinates (flat x/y plane, no antimeridian) require the x-ordinates to be ordered; an inverted x-range is always invalid. This validator exists specifically because the default (geographic) policy allows minX > maxX for antimeridian-crossing envelopes, so cartesian usage needs an explicit stricter check.","triggerScenarios":"Calling `CartesianValidator.INSTANCE.validateBBox(minX, maxX, maxY, minY)` with minX > maxX, or routing a bbox through a code path that uses CartesianValidator when the data is geographic.","commonSituations":"Using the cartesian validator on data that is actually geographic (longitude can legitimately exceed the western bound when crossing the antimeridian); argument-order mistakes passing (maxX, minX); inverted envelopes coming from upstream computations.","solutions":["If the data is geographic (lat/lon), use GeographyValidator instead — it intentionally does NOT check x-ordering.","If the data is truly cartesian, reorder or normalize so minX <= maxX before validating.","Pass arguments in the documented (minX, maxX, maxY, minY) order."],"exampleFix":"// before (geographic data routed through cartesian validator)\nCartesianValidator.INSTANCE.validateBBox(170, -170, 20, -20); // throws\n\n// after\nGeographyValidator.instance(true).validateBBox(170, -170, 20, -20); // antimeridian-crossing OK","handlingStrategy":"validation","validationCode":"if (dataIsGeographic) {\n    GeographyValidator.instance(ignoreZ).validateBBox(minX, maxX, maxY, minY);\n} else {\n    if (minX > maxX) throw new IllegalArgumentException(\"cartesian minX > maxX\");\n    CartesianValidator.INSTANCE.validateBBox(minX, maxX, maxY, minY);\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Pick the validator by CRS: GeographyValidator for lat/lon, CartesianValidator for flat x/y.","Geographic data legitimately has minX > maxX across the antimeridian — only cartesian rejects it.","Pass bbox ordinates in (minX, maxX, maxY, minY) order."],"tags":["geometry","validation","cartesian","bounding-box","validator","libs-geo"],"analyzedSha":"db6a809a667c081ca1dc7500389d26975573215f","analyzedAt":"2026-08-12T01:39:14.192Z","schemaVersion":2},"datasetVersion":"2026-08-12T12:17:08.281Z"}