{"record":{"id":"466d05f30872799d","repo":"elastic/elasticsearch","slug":"only-one-z-value-is-specified","errorCode":null,"errorMessage":"only one z value is specified","messagePattern":"only one z value is specified","errorType":"validation","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"libs/geo/src/main/java/org/elasticsearch/geometry/Rectangle.java","lineNumber":78,"sourceCode":"        this(minX, maxX, maxY, minY, Double.NaN, Double.NaN);\n    }\n\n    /**\n     * Constructs a bounding box by first validating the provided latitude and longitude coordinates\n     */\n    public Rectangle(double minX, double maxX, double maxY, double minY, double minZ, double maxZ) {\n        this.minX = minX;\n        this.maxX = maxX;\n        this.minY = minY;\n        this.maxY = maxY;\n        this.minZ = minZ;\n        this.maxZ = maxZ;\n        empty = false;\n        if (maxY < minY) {\n            throw new IllegalArgumentException(\"max y cannot be less than min y\");\n        }\n        if (Double.isNaN(minZ) != Double.isNaN(maxZ)) {\n            throw new IllegalArgumentException(\"only one z value is specified\");\n        }\n    }\n\n    public double getMinY() {\n        return minY;\n    }\n\n    public double getMinX() {\n        return minX;\n    }\n\n    public double getMinZ() {\n        return minZ;\n    }\n\n    public double getMaxY() {\n        return maxY;\n    }","sourceCodeStart":60,"sourceCodeEnd":96,"githubUrl":"https://github.com/elastic/elasticsearch/blob/db6a809a667c081ca1dc7500389d26975573215f/libs/geo/src/main/java/org/elasticsearch/geometry/Rectangle.java#L60-L96","documentation":"Thrown by the 6-argument Rectangle constructor when exactly one of minZ/maxZ is NaN. The Z (altitude) dimension is optional for a Rectangle, but the library requires both Z bounds to be either present or absent — a half-specified Z range is treated as a programming error rather than a default.","triggerScenarios":"Calling `new Rectangle(minX, maxX, maxY, minY, minZ, maxZ)` where `Double.isNaN(minZ) != Double.isNaN(maxZ)` — e.g. minZ=Double.NaN with maxZ=100.0, or minZ=0.0 with maxZ=Double.NaN.","commonSituations":"Mixing 2D and 3D data sources where some records carry altitude and others do not; defaulting one Z bound to NaN as a 'no bound' sentinel while leaving the other populated; copy-paste from a 2D-only code path that left one Z argument unset.","solutions":["Pass Double.NaN for BOTH minZ and maxZ when the rectangle is 2D: `new Rectangle(minX, maxX, maxY, minY, Double.NaN, Double.NaN)`.","If the rectangle is 3D, supply concrete numeric values for both minZ and maxZ.","Audit upstream data: reject or normalize records where only one of the two altitude fields is present before they reach construction."],"exampleFix":"// before\nnew Rectangle(0, 10, 20, -20, Double.NaN, 50.0); // one z specified\n\n// after (2D)\nnew Rectangle(0, 10, 20, -20, Double.NaN, Double.NaN);\n// after (3D)\nnew Rectangle(0, 10, 20, -20, 0.0, 50.0);","handlingStrategy":"validation","validationCode":"boolean zSpecified = !Double.isNaN(minZ) || !Double.isNaN(maxZ);\nboolean zComplete = !Double.isNaN(minZ) && !Double.isNaN(maxZ);\nif (zSpecified && !zComplete) throw new IllegalArgumentException(\"Specify both z bounds or neither\");\nnew Rectangle(minX, maxX, maxY, minY, minZ, maxZ);","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Treat Z as a pair: always set both minZ and maxZ, or set both to Double.NaN.","Centralize 2D-vs-3D rectangle construction in two named factory methods so the NaN pairing is enforced by the API.","When ingesting data with optional altitude, normalize half-specified Z to fully unspecified (NaN) or to a 0-to-value range before construction."],"tags":["geometry","rectangle","validation","altitude","nan","libs-geo"],"backgroundTag":null,"analyzedSha":"db6a809a667c081ca1dc7500389d26975573215f","analyzedAt":"2026-08-12T01:39:14.192Z","schemaVersion":2},"datasetVersion":"2026-08-13T09:17:06.757Z"}