run-llama/llama_index · error · ValueError

Cannot specify both system_prompt and prefix_messages

Error message

Cannot specify both system_prompt and prefix_messages

What it means

ContextChatEngine.from_defaults() raises ValueError when both system_prompt and prefix_messages are supplied. The two parameters are alternative ways to seed the leading messages: system_prompt is shorthand that gets converted into a single system-role prefix message, so providing both makes the intent ambiguous and the engine refuses to guess which to keep.

Source

Thrown at llama-index-core/llama_index/core/chat_engine/context.py:119

        system_prompt: Optional[str] = None,
        prefix_messages: Optional[List[ChatMessage]] = None,
        node_postprocessors: Optional[List[BaseNodePostprocessor]] = None,
        context_template: Optional[Union[str, PromptTemplate]] = None,
        context_refine_template: Optional[Union[str, PromptTemplate]] = None,
        llm: Optional[LLM] = None,
        **kwargs: Any,
    ) -> "ContextChatEngine":
        """Initialize a ContextChatEngine from default parameters."""
        llm = llm or Settings.llm

        chat_history = chat_history or []
        memory = memory or Memory.from_defaults(
            chat_history=chat_history, token_limit=llm.metadata.context_window - 256
        )

        if system_prompt is not None:
            if prefix_messages is not None:
                raise ValueError(
                    "Cannot specify both system_prompt and prefix_messages"
                )
            prefix_messages = [
                ChatMessage(content=system_prompt, role=llm.metadata.system_role)
            ]

        prefix_messages = prefix_messages or []
        node_postprocessors = node_postprocessors or []

        return cls(
            retriever,
            llm=llm,
            memory=memory,
            prefix_messages=prefix_messages,
            node_postprocessors=node_postprocessors,
            callback_manager=Settings.callback_manager,
            context_template=context_template,
            context_refine_template=context_refine_template,

View on GitHub (pinned to afd0fef371)

Solutions

  1. Keep only one: pass system_prompt for a plain system message, or prefix_messages when you need multiple/role-controlled leading messages
  2. If you need both a system message and extra prefix messages, fold the system message into prefix_messages with role=llm.metadata.system_role
  3. Audit shared builder functions that blindly forward both kwargs

Example fix

# before
engine = ContextChatEngine.from_defaults(
    retriever=r,
    system_prompt='You are a helpful assistant.',
    prefix_messages=[ChatMessage(role='system', content='Be terse')],
)  # ValueError

# after
from llama_index.core.llms import ChatMessage, MessageRole
engine = ContextChatEngine.from_defaults(
    retriever=r,
    prefix_messages=[
        ChatMessage(role=MessageRole.SYSTEM, content='You are a helpful assistant. Be terse.'),
    ],
)
Defensive patterns

Strategy: validation

Validate before calling

if system_prompt is not None:
    assert prefix_messages is None, 'Pass only one of system_prompt or prefix_messages to ContextChatEngine'

Try / catch

try:
    engine = ContextChatEngine.from_defaults(retriever=r, system_prompt=sp, prefix_messages=pm)
except ValueError as e:
    if 'Cannot specify both' in str(e):
        engine = ContextChatEngine.from_defaults(retriever=r, prefix_messages=pm or None)
    else:
        raise

Prevention

When it happens

Trigger: ContextChatEngine.from_defaults(retriever=r, system_prompt='You are...', prefix_messages=[ChatMessage(...)]) — the inner `if prefix_messages is not None` check fires when system_prompt was already provided.

Common situations: Config systems that set both a 'system prompt' field and an 'advanced' prefix_messages field; incrementally adding prefix_messages for few-shot examples without removing an earlier system_prompt; merging code from two examples.

Related errors


AI-assisted analysis of run-llama/llama_index@afd0fef371 (2026-08-15). Data as JSON: /api/errors/51ec1619af9ff06d. Report an issue: GitHub.