alibaba/spring-ai-alibaba · error

Last message is not an AssistantMessage, cannot process…

Error message

Last message is not an AssistantMessage, cannot process human feedback.

What it means

HumanInTheLoopHook.afterModel logs a warning when feedback rejection is requested but the last message is not an AssistantMessage — tool-call rewriting/removal can only apply to assistant messages carrying tool calls, so the feedback cannot be processed.

Solutions

  1. Ensure the interrupt happened after a model response containing tool calls
  2. Verify message ordering in state before resuming with feedback
  3. Ignore for non-tool-call interruptions; proceed without message rewriting
Defensive patterns

Strategy: type-guard

When it happens

Trigger: Thrown at spring-ai-alibaba-agent-framework/src/main/java/com/alibaba/cloud/ai/graph/agent/hook/hip/HumanInTheLoopHook.java:141 when the library encounters an invalid state.

Common situations: See trigger scenarios.


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

Appendix: source

Thrown at spring-ai-alibaba-agent-framework/src/main/java/com/alibaba/cloud/ai/graph/agent/hook/hip/HumanInTheLoopHook.java:141

				newMessages.add(AssistantMessage.builder()
					.content(assistantMessage.getText())
					.properties(assistantMessage.getMetadata())
					.toolCalls(newToolCalls)
					.media(assistantMessage.getMedia())
					.build());
				newMessages.add(new RemoveByHash<>(assistantMessage));
			}

			// ToolResponseMessages must be added after AssistantMessage
			if (!rejectedMessage.getResponses().isEmpty()) {
				newMessages.add(rejectedMessage);
			}

			updates.put("messages", newMessages);
			return CompletableFuture.completedFuture(updates);
		}
		else {
			log.warn("Last message is not an AssistantMessage, cannot process human feedback.");
		}

		return CompletableFuture.completedFuture(Map.of());
	}

	@Override
	public Optional<InterruptionMetadata> interrupt(String nodeId, OverAllState state, RunnableConfig config) {
		AssistantMessage lastMessage = getLastAssistantMessage(state);

		if (lastMessage == null || !lastMessage.hasToolCalls()) {
			return Optional.empty();
		}

		Optional<Object> feedback = config.metadata(RunnableConfig.HUMAN_FEEDBACK_METADATA_KEY);
		if (feedback.isPresent()) {
			if (!(feedback.get() instanceof InterruptionMetadata)) {
				throw new IllegalArgumentException("Human feedback metadata must be of type InterruptionMetadata.");
			}

View on GitHub (pinned to f82da0b50f)