alibaba/spring-ai-alibaba · warning · RuntimeException

user define param: + userParamParam.getField() + is empty

Error message

user define param: + userParamParam.getField() + is empty

What it means

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.

Source

Thrown at spring-ai-alibaba-admin/spring-ai-alibaba-admin-server-core/src/main/java/com/alibaba/cloud/ai/studio/core/base/manager/AppComponentManager.java:648

					else {
						agentRequest.setMessages(messages);
					}
				}
			}
			// handle user params
			AppComponentConfig appComponentInputConfig = getAppComponentInputConfig(appComponentByCode);
			AppComponentConfig.Input input1 = appComponentInputConfig.getInput();
			for (AppComponentConfig.UserParams userParam : input1.getUserParams()) {
				HashMap<String, Object> paramMap = new HashMap<>();
				for (AppComponentConfig.Params userParamParam : userParam.getParams()) {
					if (bizVars.containsKey(userParamParam.getAlias())) {
						paramMap.put(userParamParam.getField(), bizVars.get(userParamParam.getAlias()));
					}
					else if (userParamParam.getDefaultValue() != null) {
						paramMap.put(userParamParam.getField(), userParamParam.getDefaultValue());
					}
					else if (userParamParam.getRequired()) {
						throw new RuntimeException("user define param:" + userParamParam.getField() + "is empty");
					}
				}
				if (!paramMap.isEmpty()) {
					userDefinedParamMap.put(userParam.getCode(), paramMap);
				}
			}
			agentRequest.setExtraPrams(userDefinedParamMap);
			return agentRequest;
		}
		return null;
	}

	/**
	 * Build workflow request from app component request.
	 * @param request App component request
	 * @return Workflow request object
	 */
	private WorkflowRequest buildWorkflowRequest(AppComponentRequest request) {

View on GitHub (pinned to f82da0b50f)

Solutions

  1. Set a non-null result (approve/reject decision or ToolResponse payload) on every ToolFeedback before resuming
  2. Validate the client payload (result field present and non-empty) before calling resume
  3. Check deserialization mapping after upgrading InterruptionMetadata/ToolFeedback versions
  4. Reject incomplete feedback in your UI layer with a clear user-facing error

Example fix

// before
new ToolFeedback(call.name(), call.id(), null); // result missing
// after
new ToolFeedback(call.name(), call.id(), ToolFeedbackResult.approve("ok"));
Defensive patterns

Strategy: validation

Validate before calling

for (InterruptionMetadata.ToolFeedback tf : toolFeedbacks) {
    if (tf.getResult() == null) throw new IllegalArgumentException("Feedback for tool " + tf.getName() + " (id=" + tf.getId() + ") must include a result");
}

Type guard

boolean allFeedbackComplete(List<InterruptionMetadata.ToolFeedback> fb) {
    return fb.stream().allMatch(f -> f.getResult() != null);
}

Prevention

When it happens

Trigger: interrupt() -> validateFeedback() finds matchedFeedback.getResult() == null — e.g. feedback entry constructed with only name/id (or action left unset) and no result payload.

Common situations: UI submitting an approval click without the result field; client schema drift after upgrade so result deserializes as null; partial feedback objects built programmatically.

Understand the failure class

Background: "must not be empty", "cannot be empty" — required-field validation errors across open-source libraries — this error's family across 41 libraries.

Related errors


AI-assisted analysis of alibaba/spring-ai-alibaba@f82da0b50f (2026-09-09). Data as JSON: /api/errors/250d6978cf3522f8. Report an issue: GitHub.