{"record":{"id":"f9797953f503f669","repo":"alibaba/spring-ai-alibaba","slug":"selectionmodel-is-required","errorCode":null,"errorMessage":"selectionModel is required","messagePattern":"selectionModel is required","errorType":"validation","errorClass":"IllegalStateException","httpStatus":null,"severity":"error","filePath":"spring-ai-alibaba-agent-framework/src/main/java/com/alibaba/cloud/ai/graph/agent/interceptor/toolselection/ToolSelectionInterceptor.java","lineNumber":240,"sourceCode":"\t\t\t\tthrow new IllegalArgumentException(\"maxTools must be > 0\");\n\t\t\t}\n\t\t\tthis.maxTools = maxTools;\n\t\t\treturn this;\n\t\t}\n\n\t\tpublic Builder alwaysInclude(Set<String> alwaysInclude) {\n\t\t\tthis.alwaysInclude = alwaysInclude;\n\t\t\treturn this;\n\t\t}\n\n\t\tpublic Builder alwaysInclude(String... toolNames) {\n\t\t\tthis.alwaysInclude = new HashSet<>(Arrays.asList(toolNames));\n\t\t\treturn this;\n\t\t}\n\n\t\tpublic ToolSelectionInterceptor build() {\n\t\t\tif (selectionModel == null) {\n\t\t\t\tthrow new IllegalStateException(\"selectionModel is required\");\n\t\t\t}\n\t\t\treturn new ToolSelectionInterceptor(this);\n\t\t}\n\t}\n}\n","sourceCodeStart":222,"sourceCodeEnd":246,"githubUrl":"https://github.com/alibaba/spring-ai-alibaba/blob/f82da0b50f35744c13968191be2b1cd2452ef550/spring-ai-alibaba-agent-framework/src/main/java/com/alibaba/cloud/ai/graph/agent/interceptor/toolselection/ToolSelectionInterceptor.java#L222-L246","documentation":"ToolSelectionInterceptor.build() performs a post-configuration check and throws IllegalStateException when no selection model (a ChatModel used to decide which tools to keep) was supplied. Without a model the interceptor cannot function, so building is refused.","triggerScenarios":"Calling ToolSelectionInterceptor.builder().build() without ever calling the builder method that sets the selectionModel.","commonSituations":"Constructing the builder from config where the model bean is missing or null; copying interceptor setup code and dropping the model call; the model is conditionally injected and absent in the active profile.","solutions":["Call the builder's selection-model setter with a ChatModel instance before build()","Ensure the ChatModel bean is available in the Spring context / application profile","Reorder construction so the model is created before the interceptor is built"],"exampleFix":"// before\nToolSelectionInterceptor.builder().maxTools(3).build(); // IllegalStateException\n// after\nToolSelectionInterceptor.builder()\n    .selectionModel(chatModel)\n    .maxTools(3)\n    .build();","handlingStrategy":"validation","validationCode":"assert chatModel != null : \"selectionModel must be set before ToolSelectionInterceptor.build()\";","typeGuard":"boolean canBuild(ToolSelectionInterceptor.Builder b) { return b != null && selectionModel != null; }","tryCatchPattern":"try { interceptor = b.build(); } catch (IllegalStateException e) { throw new BeanInitializationException(\"ToolSelectionInterceptor misconfigured\", e); }","preventionTips":["Always set the selection model immediately after obtaining the builder","Use constructor/Spring injection so the ChatModel cannot be null","Add a startup smoke test that builds all interceptors"],"tags":["java","builder","missing-config","tool-selection"],"backgroundTag":"missing-required-option","analyzedSha":"f82da0b50f35744c13968191be2b1cd2452ef550","analyzedAt":"2026-09-09T15:32:42.421Z","contentChangedAt":"2026-09-09T15:32:42.421Z","schemaVersion":2},"datasetVersion":"2026-09-14T11:17:12.474Z"}