affaan-m/ECC · error · ValueError

Pass either config or PromptBuilder keyword options, not bot

Error message

Pass either config or PromptBuilder keyword options, not both

What it means

PromptBuilder.__init__ accepts either a PromptConfig object OR individual keyword overrides (system_template, user_template, include_tools_in_system, tool_format), but not both. Passing config plus any non-None keyword is rejected to keep the two construction modes unambiguous.

Source

Thrown at src/llm/prompt/builder.py:33

    include_tools_in_system: bool = True
    tool_format: str = "native"


class PromptBuilder:
    def __init__(
        self,
        config: PromptConfig | None = None,
        *,
        system_template: str | None = None,
        user_template: str | None = None,
        include_tools_in_system: bool | None = None,
        tool_format: str | None = None,
    ) -> None:
        if config is not None and any(
            value is not None
            for value in (system_template, user_template, include_tools_in_system, tool_format)
        ):
            raise ValueError("Pass either config or PromptBuilder keyword options, not both")

        if config is None:
            defaults = PromptConfig()
            config = PromptConfig(
                system_template=(
                    system_template if system_template is not None else defaults.system_template
                ),
                user_template=(
                    user_template if user_template is not None else defaults.user_template
                ),
                include_tools_in_system=(
                    include_tools_in_system
                    if include_tools_in_system is not None
                    else defaults.include_tools_in_system
                ),
                tool_format=(
                    tool_format if tool_format is not None else defaults.tool_format
                ),

View on GitHub (pinned to 01e15490f0)

Solutions

  1. If you have a config, pass only the config and edit its fields before construction.
  2. If you want overrides, pass only the keyword arguments — the builder will assemble a PromptConfig from them.
  3. Use get_provider_builder(provider_name) for the standard provider presets instead of mixing config and kwargs.

Example fix

# before
cfg = PromptConfig(tool_format='openai')
builder = PromptBuilder(cfg, system_template='You are X')

# after (option A: edit the config)
cfg = PromptConfig(tool_format='openai', system_template='You are X')
builder = PromptBuilder(cfg)

# after (option B: kwargs only)
builder = PromptBuilder(system_template='You are X', tool_format='openai')
Defensive patterns

Strategy: validation

Validate before calling

from llm.prompt.builder import PromptBuilder, PromptConfig

def build_prompt(config: PromptConfig | None = None, **overrides):
    if config is not None and overrides:
        raise ValueError('Pass either config or overrides, not both')
    return PromptBuilder(config, **overrides) if not config else PromptBuilder(config)

Try / catch

from llm.prompt.builder import PromptBuilder, PromptConfig
try:
    builder = PromptBuilder(config, system_template='X')
except ValueError:
    builder = PromptBuilder(config)  # drop the override

Prevention

When it happens

Trigger: Passing PromptBuilder(my_config, system_template='X'); passing config=cfg and tool_format='openai' together; refactoring code that previously built a config and now also passes a per-call override.

Common situations: Migrating from one construction style to the other and forgetting to remove the old argument; helper functions that thread both a config object and override kwargs through to the builder.

Related errors


AI-assisted analysis of affaan-m/ECC@01e15490f0 (2026-08-13). Data as JSON: /api/errors/7e7e0a927045538a. Report an issue: GitHub.