zylon-ai/private-gpt · error · ValueError

include_system can only be used with 'last' strategy

Error message

include_system can only be used with 'last' strategy

What it means

Companion constraint to error 154: the TrimmingMemory validator raises when include_system is truthy (note the default is True) while trim_strategy is TrimStrategy.FIRST. include_system preserves system messages when trimming with the LAST strategy; under FIRST strategy the semantics are undefined in this implementation, so the combination is rejected. Because include_system defaults to True, choosing FIRST strategy while merely leaving defaults can trigger this.

Source

Thrown at private_gpt/components/memory/trimming_memory.py:102

        if tokenizer_fn is None:
            # TODO: Replace with a default tokenizer function
            raise ValueError("tokenizer_fn must be provided.")

        # Validate text splitter
        text_splitter = values.get("text_splitter")
        if text_splitter is None:
            values["text_splitter"] = _default_text_splitter

        # Validate strategy-specific constraints
        trim_strategy = values.get("trim_strategy", TrimStrategy.LAST)
        start_on = values.get("start_on")
        include_system = values.get("include_system", True)

        if start_on and trim_strategy == TrimStrategy.FIRST:
            raise ValueError("start_on can only be used with 'last' strategy")

        if include_system and trim_strategy == TrimStrategy.FIRST:
            raise ValueError("include_system can only be used with 'last' strategy")

        return values

    @classmethod
    def from_defaults(
        cls,
        chat_history: list[ChatMessage] | None = None,
        llm: LLM | None = None,
        chat_store: BaseChatStore | None = None,
        chat_store_key: str = DEFAULT_CHAT_STORE_KEY,
        token_limit: int | None = None,
        trim_strategy: TrimStrategy = TrimStrategy.LAST,
        include_system: bool = True,
        allow_partial: bool = False,
        start_on: MessageRole | list[MessageRole] | None = None,
        end_on: MessageRole | list[MessageRole] | None = None,
        tokenizer_fn: TokenizerFn | None = None,
        text_splitter: Callable[[str], list[str]] | None = None,

View on GitHub (pinned to 4a030776a3)

Solutions

  1. When using TrimStrategy.FIRST, set include_system=False explicitly.
  2. Or stay with the default LAST strategy if you need system-message preservation.
  3. Add cross-field checks in config validation so strategy flips force include_system review.

Example fix

# before
TrimmingMemory(trim_strategy=TrimStrategy.FIRST, ...)

# after
TrimmingMemory(trim_strategy=TrimStrategy.FIRST, include_system=False, ...)
Defensive patterns

Strategy: validation

Validate before calling

if trim_strategy == 'first':
    include_system = False  # FIRST strategy forbids include_system
kwargs['trim_strategy'] = trim_strategy
kwargs['include_system'] = include_system

Prevention

When it happens

Trigger: TrimmingMemory(trim_strategy=TrimStrategy.FIRST) with include_system left at its default True; explicitly passing include_system=True with FIRST; switching an existing memory config to 'first' without adding include_system=False.

Common situations: Adopting FIRST trimming in an existing deployment where the config never mentioned include_system; config migration tools that preserve old defaults when the strategy changes.

Related errors


AI-assisted analysis of zylon-ai/private-gpt@4a030776a3 (2026-08-15). Data as JSON: /api/errors/3df6e3d7c7d4b2ac. Report an issue: GitHub.