{"record":{"id":"e8cc3496cf9d9a57","repo":"quickwit-oss/quickwit","slug":"both-lt-and-lte-are-set","errorCode":null,"errorMessage":"both lt and lte are set","messagePattern":"both lt and lte are set","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"quickwit/quickwit-query/src/elastic_query_dsl/range_query.rs","lineNumber":117,"sourceCode":"                lte.map(|v| parse_and_convert(v, &parser)).transpose()?,\n            )\n        } else {\n            (gt, gte, lt, lte)\n        };\n\n        let range_query_ast = crate::query_ast::RangeQuery {\n            field,\n            lower_bound: match (gt, gte) {\n                (Some(_gt), Some(_gte)) => {\n                    anyhow::bail!(\"both gt and gte are set\")\n                }\n                (Some(gt), None) => Bound::Excluded(gt),\n                (None, Some(gte)) => Bound::Included(gte),\n                (None, None) => Bound::Unbounded,\n            },\n            upper_bound: match (lt, lte) {\n                (Some(_lt), Some(_lte)) => {\n                    anyhow::bail!(\"both lt and lte are set\")\n                }\n                (Some(lt), None) => Bound::Excluded(lt),\n                (None, Some(lte)) => Bound::Included(lte),\n                (None, None) => Bound::Unbounded,\n            },\n        };\n        let ast: QueryAst = range_query_ast.into();\n        Ok(ast.boost(boost))\n    }\n}\n\nfn parse_and_convert(literal: JsonLiteral, parser: &StrptimeParser) -> anyhow::Result<JsonLiteral> {\n    if let JsonLiteral::String(date_time_str) = literal {\n        let parsed_date_time = parser\n            .parse_date_time(&date_time_str)\n            .map_err(|reason| anyhow::anyhow!(\"Failed to parse date time: {}\", reason))?;\n        let parsed_date_time_rfc3339 = parsed_date_time.format(&Rfc3339)?;\n        Ok(JsonLiteral::String(parsed_date_time_rfc3339))","sourceCodeStart":99,"sourceCodeEnd":135,"githubUrl":"https://github.com/quickwit-oss/quickwit/blob/a39730c5cdcd1a4fe798403737ae293999ea21f8/quickwit/quickwit-query/src/elastic_query_dsl/range_query.rs#L99-L135","documentation":"Symmetric to the lower bound check: the upper bound of a range query is built from `lt` (exclusive) and `lte` (inclusive), and supplying both keys is ambiguous. The conversion in range_query.rs bails with this error before constructing the RangeQuery AST.","triggerScenarios":"Sending a range query JSON containing both `lt` and `lte` keys, e.g. `{\"range\": {\"ts\": {\"lt\": 200, \"lte\": 100}}}`, through the Elastic range query conversion.","commonSituations":"Query builders that always serialize both upper-bound keys; users copying Elasticsearch examples that use lt alongside lte; templates parameterizing both exclusive and inclusive endpoints.","solutions":["Keep only `lte` for an inclusive upper bound, or only `lt` for exclusive.","In generated queries, serialize only the bound key that is actually set.","Add client-side validation rejecting range objects with both upper-bound keys."],"exampleFix":"// before\n{\"range\": {\"timestamp\": {\"lt\": \"2024-02-01\", \"lte\": \"2024-01-31T23:59:59Z\"}}}\n// after\n{\"range\": {\"timestamp\": {\"lt\": \"2024-02-01\"}}}","handlingStrategy":"validation","validationCode":"if range.contains_key(\"lt\") && range.contains_key(\"lte\") {\n    return Err(\"range upper bound: set only one of lt/lte\");\n}","typeGuard":null,"tryCatchPattern":"match res {\n    Err(e) if e.to_string().contains(\"both lt and lte\") => {\n        // serialize only one upper bound and retry\n    }\n    r => r?,\n}","preventionTips":["Serialize upper bounds conditionally (exactly one key).","Document inclusive/exclusive semantics so users choose lt vs lte deliberately.","Validate range objects client-side before hitting the API."],"tags":["range-query","query-dsl","validation"],"backgroundTag":"mutually-exclusive-options","analyzedSha":"a39730c5cdcd1a4fe798403737ae293999ea21f8","analyzedAt":"2026-09-08T13:19:37.784Z","contentChangedAt":"2026-09-08T13:19:37.784Z","schemaVersion":2},"datasetVersion":"2026-09-14T16:17:12.679Z"}