{"record":{"id":"36c982e33b27b2fb","repo":"alibaba/spring-ai-alibaba","slug":"hybrid-alpha-should-be-between-0-1","errorCode":null,"errorMessage":"hybrid alpha should be between 0 ~ 1.","messagePattern":"hybrid alpha should be between 0 ~ 1\\.","errorType":"exception","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"spring-ai-alibaba-admin/spring-ai-alibaba-admin-server-core/src/main/java/org/springframework/ai/vectorstore/elasticsearch/ElasticsearchVectorStore.java","lineNumber":502,"sourceCode":"\t\t\t\t\t\t.size((int) (1.5 * searchRequest.getTopK())),\n\t\t\t\t\tDocument.class);\n\n\t\t\treturn res.hits()\n\t\t\t\t.hits()\n\t\t\t\t.stream()\n\t\t\t\t.map(x -> toDocument(x, SearchType.FULL_TEXT))\n\t\t\t\t.collect(Collectors.toList());\n\t\t}\n\t\tcatch (IOException e) {\n\t\t\tthrow new BizException(ErrorCode.DOCUMENT_RETRIEVAL_ERROR.toError(), e);\n\t\t}\n\t}\n\n\tprotected List<Document> searchByHybrid(SearchRequest searchRequest) {\n\t\tList<CompletableFuture<List<Document>>> futureList = new ArrayList<>();\n\n\t\tif (searchRequest.getHybridWeight() < 0 || searchRequest.getHybridWeight() > 1) {\n\t\t\tthrow new IllegalArgumentException(\"hybrid alpha should be between 0 ~ 1.\");\n\t\t}\n\n\t\ttry {\n\t\t\tCompletableFuture<List<Document>> textFuture = CompletableFuture.supplyAsync(() -> {\n\t\t\t\tint textTopK = Math.round(searchRequest.getTopK() * (1 - searchRequest.getHybridWeight()));\n\t\t\t\treturn searchByFullText(SearchRequest.builder()\n\t\t\t\t\t.query(searchRequest.getQuery())\n\t\t\t\t\t.similarityThreshold(searchRequest.getSimilarityThreshold())\n\t\t\t\t\t.topK(textTopK)\n\t\t\t\t\t.filterExpression(searchRequest.getFilterExpression())\n\t\t\t\t\t.build());\n\t\t\t}, DEFAULT_TASK_EXECUTOR);\n\t\t\tfutureList.add(textFuture);\n\n\t\t\t// 基于向量检索召回内容\n\t\t\tCompletableFuture<List<Document>> vectorFuture = CompletableFuture.supplyAsync(() -> {\n\t\t\t\tint textTopK = Math.round(searchRequest.getTopK() * searchRequest.getHybridWeight());\n\t\t\t\treturn searchBySemantic(SearchRequest.builder()","sourceCodeStart":484,"sourceCodeEnd":520,"githubUrl":"https://github.com/alibaba/spring-ai-alibaba/blob/f82da0b50f35744c13968191be2b1cd2452ef550/spring-ai-alibaba-admin/spring-ai-alibaba-admin-server-core/src/main/java/org/springframework/ai/vectorstore/elasticsearch/ElasticsearchVectorStore.java#L484-L520","documentation":"searchByHybrid validates that the SearchRequest hybridWeight (the alpha balancing semantic vs full-text scoring) lies within [0,1]; outside that range it throws IllegalArgumentException(\"hybrid alpha should be between 0 ~ 1.\"). A hybrid search with an out-of-range alpha is meaningless and rejected up front.","triggerScenarios":"Calling VectorStore.similaritySearch with searchType=HYBRID and SearchRequest.builder().hybridWeight(x) where x < 0 or x > 1 (e.g. passing a percentage like 50 instead of 0.5).","commonSituations":"Confusing percentage (0–100) with fraction (0–1) when setting hybrid weight; inverting the weight (1 - weight); copying a weight from a different library that uses a different scale.","solutions":["Clamp hybridWeight to [0,1] before building the SearchRequest.","Convert percentage inputs: use 0.5 instead of 50.","Validate user-supplied config values at load time and reject out-of-range alphas early.","Use 0.0 for pure full-text and 1.0 for pure semantic if you intended an extreme."],"exampleFix":"// before\nSearchRequest req = SearchRequest.builder().query(\"q\")\n    .searchType(SearchType.HYBRID).hybridWeight(50).build(); // throws\n// after\ndouble alpha = Math.max(0.0, Math.min(1.0, config.getHybridAlpha()));\nSearchRequest req = SearchRequest.builder().query(\"q\")\n    .searchType(SearchType.HYBRID).hybridWeight(alpha).build();","handlingStrategy":"validation","validationCode":"// Java\ndouble w = searchRequest.getHybridWeight();\nif (w < 0.0 || w > 1.0) throw new IllegalArgumentException(\"hybridWeight must be within [0,1], got \" + w);","typeGuard":"static double clampHybridWeight(Double w) {\n    if (w == null) return 0.5; // sensible default\n    return Math.max(0.0, Math.min(1.0, w));\n}","tryCatchPattern":"try { return vectorStore.similaritySearch(request); } catch (IllegalArgumentException e) {\n    if (e.getMessage().contains(\"hybrid alpha\")) {\n        SearchRequest fixed = request.mutate().hybridWeight(clampHybridWeight(request.getHybridWeight())).build();\n        return vectorStore.similaritySearch(fixed);\n    }\n    throw e;\n}","preventionTips":["Validate hybridWeight at config-load time, not at search time.","Remember the scale is fractional 0–1, not percentage 0–100.","Sanitize user-provided alpha values with clamping before building SearchRequest.","Document the valid range wherever hybrid search is exposed to users."],"tags":["elasticsearch","vector-store","hybrid-search","validation"],"backgroundTag":"value-out-of-range","analyzedSha":"f82da0b50f35744c13968191be2b1cd2452ef550","analyzedAt":"2026-09-09T15:32:42.421Z","contentChangedAt":"2026-09-09T15:32:42.421Z","schemaVersion":2},"datasetVersion":"2026-09-17T15:17:12.973Z"}