alibaba/spring-ai-alibaba · warning

Detected SystemMessages in the message list. There should…

Error message

Detected {} SystemMessages in the message list. There should typically be only one SystemMessage. Multiple SystemMessages may cause unexpected behavior or model confusion.

What it means

AgentLlmNode.appendSystemPromptIfNeeded counts SystemMessages in the outgoing message list and warns when more than two are present. Multiple SystemMessages are unusual — most chat models expect one system prompt — and can confuse the model or be dropped/merged unpredictably by providers. This is a diagnostic warning; the message list is returned unchanged.

Solutions

  1. Deduplicate SystemMessages: keep a single system prompt and merge additional instructions into it (concatenate instead of append).
  2. When appending the configured system prompt, first strip or replace existing SystemMessages in the history.
  3. Sanitize persisted/restored history at load time so only one SystemMessage survives.
  4. If multiple system blocks are intentional and your provider supports them, treat the warning as informational and document the design.

Example fix

// before
messages.add(new SystemMessage(additionalInstructions));
// after
messages.removeIf(m -> m instanceof SystemMessage);
messages.add(0, new SystemMessage(basePrompt + "\n\n" + additionalInstructions));
Defensive patterns

Strategy: validation

Validate before calling

static void assertSingleSystemMessage(List<Message> messages) {
    long n = messages.stream().filter(m -> m instanceof SystemMessage).count();
    if (n > 1) throw new IllegalStateException("Multiple SystemMessages: " + n);
}

Type guard

static List<Message> keepFirstSystemMessage(List<Message> messages) {
    boolean seen = false;
    List<Message> out = new ArrayList<>();
    for (Message m : messages) {
        if (m instanceof SystemMessage) {
            if (seen) continue;
            seen = true;
        }
        out.add(m);
    }
    return out;
}

Prevention

When it happens

Trigger: Fires from appendSystemPromptIfNeeded (reachable via messages) when messages.stream().filter(m -> m instanceof SystemMessage).count() > 2 — e.g. an agent config that injects a system prompt on top of a history that already carries several SystemMessages.

Common situations: 1) Appending per-request system prompts instead of replacing the existing one. 2) Loading persisted conversation history that contains legacy SystemMessages plus new injected prompts. 3) Multi-source prompt composition (base persona + guardrails + runtime instructions each added as a separate SystemMessage). 4) Off-by-one threshold: the code warns only above 2, so a list with exactly two SystemMessages is silently allowed.

Understand the failure class

Background: "Invalid state transition" errors: "status must be X, actually Y", "already rejected/charging/uninstalled", "cannot ... while running" — what they mean when a library rejects your call — this error's family across 31 libraries.

Related errors


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

Appendix: source

Thrown at spring-ai-alibaba-agent-framework/src/main/java/com/alibaba/cloud/ai/graph/agent/node/AgentLlmNode.java:331

	private List<Message> appendSystemPromptIfNeeded(ModelRequest modelRequest) {
		// Create a new list and copy messages from modelRequest
		List<Message> messages = new ArrayList<>(modelRequest.getMessages());

		// FIXME, there should have only one SystemMessage.
		//  Users may have added SystemMessages in hooks or somewhere else, simply remove will cause unexpected agent behaviour.
//		messages.removeIf(message -> message instanceof SystemMessage);

		// Add the SystemMessage from modelRequest at the beginning if present
		if (modelRequest.getSystemMessage() != null) {
			messages.add(0, modelRequest.getSystemMessage());
		}

		long systemMessageCount = messages.stream()
				.filter(message -> message instanceof SystemMessage)
				.count();

		if (systemMessageCount > 2) {
			logger.warn("Detected {} SystemMessages in the message list. There should typically be only one SystemMessage. " +
					"Multiple SystemMessages may cause unexpected behavior or model confusion.", systemMessageCount);
		}

		return messages;
	}

	/**
	 * Build chat options by merging toolCallbacks with the provided chatOptions.
	 * If chatOptions is null or not of type ToolCallingChatOptions, create a new ToolCallingChatOptions.
	 * If chatOptions is ToolCallingChatOptions, merge toolCallbacks (toolCallbacks takes precedence).
	 *
	 * @param chatOptions the original chat options
	 * @param toolCallbacks the tool callbacks to be included
	 * @return merged ToolCallingChatOptions
	 */
	@Nullable
	private ToolCallingChatOptions buildChatOptions(ChatOptions chatOptions, List<ToolCallback> toolCallbacks) {
		if (chatOptions == null && (toolCallbacks == null || toolCallbacks.isEmpty())) {

View on GitHub (pinned to f82da0b50f)