{"record":{"id":"e51e1e32e1142655","repo":"spring-projects/spring-ai","slug":"unsupported-value-type-for-gt-condition-only-supp","errorCode":null,"errorMessage":"Unsupported value type for GT condition. Only supports Number","messagePattern":"Unsupported value type for GT 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":129,"sourceCode":"\t\t\t\t.build());\n\t\t}\n\t\telse if (value.value() instanceof Number valueNum) {\n\t\t\tlong lValue = Long.parseLong(valueNum.toString());\n\t\t\tCondition condition = io.qdrant.client.ConditionFactory.match(identifier, lValue);\n\t\t\treturn io.qdrant.client.ConditionFactory.filter(Filter.newBuilder().addMustNot(condition).build());\n\t\t}\n\n\t\tthrow new IllegalArgumentException(\"Invalid value type for NEQ. Can either be a string or Number\");\n\n\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());","sourceCodeStart":111,"sourceCodeEnd":147,"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#L111-L147","documentation":"Filter translation guard in QdrantFilterExpressionConverter.buildGtCondition: a GT (greater-than) comparison was given a non-Number right-hand value; Qdrant range conditions only support numeric comparisons.","triggerScenarios":"Filter.builder().gt(\"createdAt\", \"2024-01-01\").build() or gt(\"price\", null) — any GT whose Value is a String date, Boolean, etc., instead of a Number.","commonSituations":"Filtering date fields with ISO-8601 strings (very common) — Qdrant ranges are numeric, so dates must be stored as epoch numbers.","solutions":["Use a numeric value for the GT comparison","Store the field as a number in Qdrant and filter numerically"],"exampleFix":"// before\nFilter.builder().gt(\"createdAt\", \"2024-01-01\").build();\n// after\nFilter.builder().gt(\"createdAt\", Instant.parse(\"2024-01-01T00:00:00Z\").getEpochSecond()).build();","handlingStrategy":"validation","validationCode":"static void checkRangeOperand(Object v) {\n    if (!(v instanceof Number)) {\n        throw new IllegalArgumentException(\"Range operand (GT/GTE/LT/LTE) must be a Number, got \" + (v == null ? \"null\" : v.getClass()));\n    }\n}","typeGuard":"static boolean isRangeCompatible(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(\"GT condition. Only supports Number\")) {\n        throw new IllegalArgumentException(\"GT requires a numeric operand; store dates as epoch numbers\", ex);\n    }\n    throw ex;\n}","preventionTips":["Store date metadata as epoch millis/seconds, never ISO strings.","Parse user-supplied numbers with Double/Long.parse before building filters.","Add ingestion-time schema validation for numeric fields."],"tags":["qdrant","filter-expression","gt","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"}