{"record":{"id":"3f1b90d85c3ec797","repo":"spring-projects/spring-ai","slug":"unsupported-value-type-for-lt-condition-only-supp","errorCode":null,"errorMessage":"Unsupported value type for LT condition. Only supports Number","messagePattern":"Unsupported value type for LT condition\\. Only supports Number","errorType":"exception","errorClass":"RuntimeException","httpStatus":null,"severity":"error","filePath":"vector-stores/spring-ai-qdrant-store/src/main/java/org/springframework/ai/vectorstore/qdrant/QdrantFilterExpressionConverter.java","lineNumber":139,"sourceCode":"\t}\n\n\tprotected Condition buildGtCondition(Key key, Value value) {\n\t\tString identifier = doKey(key);\n\t\tif (value.value() instanceof Number valueNum) {\n\t\t\tDouble dvalue = Double.parseDouble(valueNum.toString());\n\t\t\treturn io.qdrant.client.ConditionFactory.range(identifier, Range.newBuilder().setGt(dvalue).build());\n\t\t}\n\t\tthrow new RuntimeException(\"Unsupported value type for GT condition. Only supports Number\");\n\n\t}\n\n\tprotected Condition buildLtCondition(Key key, Value value) {\n\t\tString identifier = doKey(key);\n\t\tif (value.value() instanceof Number valueNum) {\n\t\t\tDouble dvalue = Double.parseDouble(valueNum.toString());\n\t\t\treturn io.qdrant.client.ConditionFactory.range(identifier, Range.newBuilder().setLt(dvalue).build());\n\t\t}\n\t\tthrow new RuntimeException(\"Unsupported value type for LT condition. Only supports Number\");\n\n\t}\n\n\tprotected Condition buildGteCondition(Key key, Value value) {\n\t\tString identifier = doKey(key);\n\t\tif (value.value() instanceof Number valueNum) {\n\t\t\tDouble dvalue = Double.parseDouble(valueNum.toString());\n\t\t\treturn io.qdrant.client.ConditionFactory.range(identifier, Range.newBuilder().setGte(dvalue).build());\n\t\t}\n\t\tthrow new RuntimeException(\"Unsupported value type for GTE condition. Only supports Number\");\n\n\t}\n\n\tprotected Condition buildLteCondition(Key key, Value value) {\n\t\tString identifier = doKey(key);\n\t\tif (value.value() instanceof Number valueNum) {\n\t\t\tDouble dvalue = Double.parseDouble(valueNum.toString());\n\t\t\treturn io.qdrant.client.ConditionFactory.range(identifier, Range.newBuilder().setLte(dvalue).build());","sourceCodeStart":121,"sourceCodeEnd":157,"githubUrl":"https://github.com/spring-projects/spring-ai/blob/98a7beda4f29d80a71c5837eb4053b03a93a46f7/vector-stores/spring-ai-qdrant-store/src/main/java/org/springframework/ai/vectorstore/qdrant/QdrantFilterExpressionConverter.java#L121-L157","documentation":"Raised while converting a parsed '<field> LT <value>' expression into a Qdrant range condition: Qdrant's Range filter only supports numeric comparisons, but the filter value given for the LT operator was not a Number (e.g. a string or boolean). The converter cannot express a less-than comparison over a non-numeric value in Qdrant, so it aborts. The fault lies in the caller's filter expression — use EQ/NE for non-numeric comparisons or supply a numeric value.","triggerScenarios":"Filter.builder().lt(\"price\", \"9.99\").build() — a numeric value supplied as a String, or any Boolean/date operand.","commonSituations":"Numbers deserialized from JSON/config as strings (e.g. reading query params as String and passing them straight into the filter).","solutions":["Use a numeric value for the LT comparison"],"exampleFix":"// before\nFilter.builder().lt(\"price\", request.getMaxPrice()) // String \"9.99\"\n// after\nFilter.builder().lt(\"price\", Double.parseDouble(request.getMaxPrice())).build();","handlingStrategy":"validation","validationCode":"static void checkLtOperand(Object v) {\n    if (!(v instanceof Number)) {\n        throw new IllegalArgumentException(\"LT operand must be a Number, got \" + (v == null ? \"null\" : v.getClass()));\n    }\n}","typeGuard":"static boolean isNumber(Object v) {\n    return v instanceof Number;\n}","tryCatchPattern":"try {\n    vectorStore.similaritySearch(req);\n} catch (RuntimeException ex) {\n    if (ex.getMessage() != null && ex.getMessage().contains(\"LT condition. Only supports Number\")) {\n        throw new IllegalArgumentException(\"LT requires a numeric operand\", ex);\n    }\n    throw ex;\n}","preventionTips":["Coerce numeric strings to Number before filtering.","Keep numeric metadata numeric at ingestion time.","Centralize operand conversion in a filter-builder helper."],"tags":["qdrant","filter-expression","lt","range","spring-ai"],"backgroundTag":"type-mismatch","analyzedSha":"98a7beda4f29d80a71c5837eb4053b03a93a46f7","analyzedAt":"2026-09-11T14:15:49.441Z","contentChangedAt":"2026-09-11T14:15:49.441Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}