{"record":{"id":"4c35da66c0162b68","repo":"jd-opensource/joyagent-jdgenie","slug":"invalid-tool-choice-toolchoice","errorCode":null,"errorMessage":"Invalid tool_choice: \" + toolChoice","messagePattern":"Invalid tool_choice: \" \\+ toolChoice","errorType":"validation","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"genie-backend/src/main/java/com/jd/genie/agent/llm/LLM.java","lineNumber":373,"sourceCode":"    }\n\n    /**\n     * 向 LLM 发送工具请求并获取响应\n     */\n    public CompletableFuture<ToolCallResponse> askTool(\n            AgentContext context,\n            List<Message> messages,\n            Message systemMsgs,\n            ToolCollection tools,\n            ToolChoice toolChoice,\n            Double temperature,\n            boolean stream,\n            int timeout\n    ) {\n        try {\n            // 验证 toolChoice\n            if (!ToolChoice.isValid(toolChoice)) {\n                throw new IllegalArgumentException(\"Invalid tool_choice: \" + toolChoice);\n            }\n            long startTime = System.currentTimeMillis();\n\n            // 设置 API 请求\n            Map<String, Object> params = new HashMap<>();\n\n            // tools\n            StringBuilder stringBuilder = new StringBuilder();\n            List<Map<String, Object>> formattedTools = new ArrayList<>();\n            if (\"struct_parse\".equals(functionCallType)) {\n                GenieConfig genieConfig = SpringContextHolder.getApplicationContext().getBean(GenieConfig.class);\n                stringBuilder.append(genieConfig.getStructParseToolSystemPrompt());\n                // base tool\n                for (BaseTool tool : tools.getToolMap().values()) {\n                    Map<String, Object> functionMap = new HashMap<>();\n                    functionMap.put(\"name\", tool.getName());\n                    functionMap.put(\"description\", tool.getDescription());\n                    functionMap.put(\"parameters\", addFunctionNameParam(tool.toParams(), tool.getName()));","sourceCodeStart":355,"sourceCodeEnd":391,"githubUrl":"https://github.com/jd-opensource/joyagent-jdgenie/blob/2417e0b8b636d941ad5fb14c59b20dddfef5375d/genie-backend/src/main/java/com/jd/genie/agent/llm/LLM.java#L355-L391","documentation":"LLM.askTool validates the toolChoice parameter against ToolChoice.isValid before issuing the request and throws IllegalArgumentException for unrecognized values. toolChoice must be one of the enum's supported values (e.g. auto/none/required or a specific tool name form).","triggerScenarios":"Calling askTool with a toolChoice string that is null, misspelled, or not a registered ToolChoice value.","commonSituations":"Hardcoded toolChoice from config with a typo, migrating from another SDK that used different tool_choice vocabulary, or building the value dynamically from user input.","solutions":["Use ToolChoice enum constants instead of raw strings","Validate with ToolChoice.isValid(value) before calling askTool","Fix typos in configured toolChoice values"],"exampleFix":"// before\nllm.askTool(messages, \"AUTO\", tools, ...);\n// after\nllm.askTool(messages, ToolChoice.AUTO.name(), tools, ...);","handlingStrategy":"validation","validationCode":"if (!ToolChoice.isValid(toolChoice)) { throw new IllegalArgumentException(\"bad toolChoice: \" + toolChoice); }","typeGuard":"boolean validChoice(String c) { return ToolChoice.isValid(c); }","tryCatchPattern":"try {\n    return llm.askTool(msgs, toolChoice, tools, ...);\n} catch (IllegalArgumentException e) {\n    return llm.askTool(msgs, ToolChoice.AUTO.name(), tools, ...);\n}","preventionTips":["Use ToolChoice enum constants, never raw strings","Validate configured values at startup","Centralize toolChoice selection in one helper"],"tags":["llm","validation","enum"],"backgroundTag":"invalid-enum-value","analyzedSha":"2417e0b8b636d941ad5fb14c59b20dddfef5375d","analyzedAt":"2026-09-08T11:28:19.414Z","contentChangedAt":"2026-09-08T11:28:19.414Z","schemaVersion":2},"datasetVersion":"2026-09-16T09:17:16.951Z"}