microsoft/semantic-kernel · error · ServiceInvalidRequestError

Multiple system messages in chat history. Only one system me

Error message

Multiple system messages in chat history. Only one system message is expected.

What it means

Raised by filter_system_message when more than one message with AuthorRole.SYSTEM exists in the ChatHistory. The Gemini API accepts a single system_instruction in the generate_content config; it does not support multiple system messages interleaved in the conversation. filter_system_message extracts the first system message for the config and rejects the presence of additional ones.

Source

Thrown at python/semantic_kernel/connectors/ai/google/shared_utils.py:23

from typing import Any

from semantic_kernel.connectors.ai.function_choice_behavior import FunctionChoiceType
from semantic_kernel.const import DEFAULT_FULLY_QUALIFIED_NAME_SEPARATOR
from semantic_kernel.contents.chat_history import ChatHistory
from semantic_kernel.contents.utils.author_role import AuthorRole
from semantic_kernel.exceptions.service_exceptions import ServiceInvalidRequestError

logger: logging.Logger = logging.getLogger(__name__)


def filter_system_message(chat_history: ChatHistory) -> str | None:
    """Filter the first system message from the chat history.

    If there are multiple system messages, raise an error.
    If there are no system messages, return None.
    """
    if len([message for message in chat_history if message.role == AuthorRole.SYSTEM]) > 1:
        raise ServiceInvalidRequestError(
            "Multiple system messages in chat history. Only one system message is expected."
        )

    for message in chat_history:
        if message.role == AuthorRole.SYSTEM:
            return message.content

    return None


FUNCTION_CHOICE_TYPE_TO_GOOGLE_FUNCTION_CALLING_MODE = {
    FunctionChoiceType.AUTO: "AUTO",
    FunctionChoiceType.NONE: "NONE",
    FunctionChoiceType.REQUIRED: "ANY",
}

# The separator used in the fully qualified name of the function instead of the default "-" separator.
# This is required since Gemini doesn't work well with "-" in the function name.

View on GitHub (pinned to c028a0c7dc)

Solutions

  1. Keep exactly one system message in the ChatHistory; update its content in place instead of adding a second.
  2. Before sending, remove all but the first system message: filter and re-insert a single consolidated system message.
  3. If you need multi-part instructions, concatenate them into a single system message's text.

Example fix

# before
history.add_system_message('You are a helpful assistant.')
history.add_system_message('Always be concise.')  # second system message

# after
history.add_system_message('You are a helpful assistant. Always be concise.')
Defensive patterns

Strategy: validation

Validate before calling

from semantic_kernel.contents.utils.author_role import AuthorRole

def validate_single_system_message(chat_history):
    system_msgs = [m for m in chat_history if m.role == AuthorRole.SYSTEM]
    if len(system_msgs) > 1:
        raise ValueError(f'Found {len(system_msgs)} system messages; Google AI allows only one.')

Type guard

from semantic_kernel.contents.utils.author_role import AuthorRole

def has_at_most_one_system_message(chat_history) -> bool:
    return sum(1 for m in chat_history if m.role == AuthorRole.SYSTEM) <= 1

Prevention

When it happens

Trigger: Adding two or more messages with role=AuthorRole.SYSTEM to a ChatHistory and then calling a Google AI chat completion method (which calls filter_system_message on the history).

Common situations: Prepending a system prompt to history that already contains a system message; accumulating conversation turns across multiple calls without clearing prior system messages; merging two ChatHistory objects that each had a system message.

Related errors


AI-assisted analysis of microsoft/semantic-kernel@c028a0c7dc (2026-08-13). Data as JSON: /api/errors/13ed239690c27963. Report an issue: GitHub.