{"record":{"id":"250d6978cf3522f8","repo":"alibaba/spring-ai-alibaba","slug":"user-define-param-userparamparam-getfield-i","errorCode":null,"errorMessage":"user define param: + userParamParam.getField() + is empty","messagePattern":"user define param: \\+ userParamParam\\.getField\\(\\) \\+ is empty","errorType":"validation","errorClass":"RuntimeException","httpStatus":500,"severity":"warning","filePath":"spring-ai-alibaba-admin/spring-ai-alibaba-admin-server-core/src/main/java/com/alibaba/cloud/ai/studio/core/base/manager/AppComponentManager.java","lineNumber":648,"sourceCode":"\t\t\t\t\telse {\n\t\t\t\t\t\tagentRequest.setMessages(messages);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\t// handle user params\n\t\t\tAppComponentConfig appComponentInputConfig = getAppComponentInputConfig(appComponentByCode);\n\t\t\tAppComponentConfig.Input input1 = appComponentInputConfig.getInput();\n\t\t\tfor (AppComponentConfig.UserParams userParam : input1.getUserParams()) {\n\t\t\t\tHashMap<String, Object> paramMap = new HashMap<>();\n\t\t\t\tfor (AppComponentConfig.Params userParamParam : userParam.getParams()) {\n\t\t\t\t\tif (bizVars.containsKey(userParamParam.getAlias())) {\n\t\t\t\t\t\tparamMap.put(userParamParam.getField(), bizVars.get(userParamParam.getAlias()));\n\t\t\t\t\t}\n\t\t\t\t\telse if (userParamParam.getDefaultValue() != null) {\n\t\t\t\t\t\tparamMap.put(userParamParam.getField(), userParamParam.getDefaultValue());\n\t\t\t\t\t}\n\t\t\t\t\telse if (userParamParam.getRequired()) {\n\t\t\t\t\t\tthrow new RuntimeException(\"user define param:\" + userParamParam.getField() + \"is empty\");\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tif (!paramMap.isEmpty()) {\n\t\t\t\t\tuserDefinedParamMap.put(userParam.getCode(), paramMap);\n\t\t\t\t}\n\t\t\t}\n\t\t\tagentRequest.setExtraPrams(userDefinedParamMap);\n\t\t\treturn agentRequest;\n\t\t}\n\t\treturn null;\n\t}\n\n\t/**\n\t * Build workflow request from app component request.\n\t * @param request App component request\n\t * @return Workflow request object\n\t */\n\tprivate WorkflowRequest buildWorkflowRequest(AppComponentRequest request) {","sourceCodeStart":630,"sourceCodeEnd":666,"githubUrl":"https://github.com/alibaba/spring-ai-alibaba/blob/f82da0b50f35744c13968191be2b1cd2452ef550/spring-ai-alibaba-admin/spring-ai-alibaba-admin-server-core/src/main/java/com/alibaba/cloud/ai/studio/core/base/manager/AppComponentManager.java#L630-L666","documentation":"HumanInTheLoopHook.validateFeedback() matched a ToolFeedback to a pending approval call but its result (the human's decision/output) is null. Validation returns false so the graph remains interrupted, waiting for complete feedback, with this warning identifying the tool and id.","triggerScenarios":"interrupt() -> validateFeedback() finds matchedFeedback.getResult() == null — e.g. feedback entry constructed with only name/id (or action left unset) and no result payload.","commonSituations":"UI submitting an approval click without the result field; client schema drift after upgrade so result deserializes as null; partial feedback objects built programmatically.","solutions":["Set a non-null result (approve/reject decision or ToolResponse payload) on every ToolFeedback before resuming","Validate the client payload (result field present and non-empty) before calling resume","Check deserialization mapping after upgrading InterruptionMetadata/ToolFeedback versions","Reject incomplete feedback in your UI layer with a clear user-facing error"],"exampleFix":"// before\nnew ToolFeedback(call.name(), call.id(), null); // result missing\n// after\nnew ToolFeedback(call.name(), call.id(), ToolFeedbackResult.approve(\"ok\"));","handlingStrategy":"validation","validationCode":"for (InterruptionMetadata.ToolFeedback tf : toolFeedbacks) {\n    if (tf.getResult() == null) throw new IllegalArgumentException(\"Feedback for tool \" + tf.getName() + \" (id=\" + tf.getId() + \") must include a result\");\n}","typeGuard":"boolean allFeedbackComplete(List<InterruptionMetadata.ToolFeedback> fb) {\n    return fb.stream().allMatch(f -> f.getResult() != null);\n}","tryCatchPattern":null,"preventionTips":["Require the decision/result field in the approval UI before submit","Add schema validation on the resume payload (result non-null)","Test deserialization after upgrading ToolFeedback/InterruptionMetadata"],"tags":["human-in-the-loop","tool-approval","null-result"],"backgroundTag":"empty-required-field","analyzedSha":"f82da0b50f35744c13968191be2b1cd2452ef550","analyzedAt":"2026-09-09T15:32:42.421Z","contentChangedAt":"2026-09-09T15:32:42.421Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}