OpenBB-finance/OpenBB · error · ValueError

Unmatched braces in prompt content: {open_braces} opening, {

Error message

Unmatched braces in prompt content: {open_braces} opening, {close_braces} closing

What it means

Pydantic validation error on PromptConfigModel.content: the template's literal brace counts differ ({ count != } count). Templates use {argument} placeholders, so unbalanced braces imply a malformed placeholder or stray brace that would break rendering. This is a naive count check — it does not validate argument references, only balance.

Source

Thrown at openbb_platform/extensions/mcp_server/openbb_mcp_server/models/mcp_config.py:112

    arguments: list[ArgumentDefinitionModel] = Field(
        default_factory=list, description="Argument definitions for the prompt"
    )
    tags: list[str] = Field(
        default_factory=list, description="Tags for categorizing the prompt"
    )

    @field_validator("content")
    @classmethod
    def validate_content(cls, v: str) -> str:
        """Validate content is not empty and contains valid template syntax."""
        if not v.strip():
            raise ValueError("Prompt content cannot be empty")

        # Check for unmatched braces
        open_braces = v.count("{")
        close_braces = v.count("}")
        if open_braces != close_braces:
            raise ValueError(
                f"Unmatched braces in prompt content: {open_braces} opening, {close_braces} closing"
            )

        return v

    @field_validator("name")
    @classmethod
    def validate_name(cls, v: str | None) -> str | None:
        """Validate prompt name if provided."""
        if v is not None:
            if not v.strip():
                raise ValueError("Prompt name cannot be empty string")
            # Check for valid identifier-like name
            if not re.match(r"^[a-zA-Z_][a-zA-Z0-9_]*$", v.strip()):
                raise ValueError(f"Prompt name '{v}' should be a valid identifier")
        return v

    @field_validator("tags")

View on GitHub (pinned to 3e071fcc2c)

Solutions

  1. Pair every opening brace with a closing one: fix {symbol → {symbol}.
  2. For literal braces in the prompt text, double them ({{ }}) if the renderer supports escaping, or restructure the text to avoid braces.
  3. Run a quick brace-count check locally before loading the config.

Example fix

# before
content: "Fetch data for {symbol and return JSON"

# after
content: "Fetch data for {symbol} and return JSON"
Defensive patterns

Strategy: validation

Validate before calling

def braces_balanced(template: str) -> bool:
    return template.count("{") == template.count("}")

# assert braces_balanced(cfg["content"]) before loading

Type guard

def is_balanced_template(content: str) -> bool:
    return isinstance(content, str) and content.count("{") == content.count("}")

Prevention

When it happens

Trigger: Writing {symbol instead of {symbol}; including JSON examples with unescaped braces (e.g. {"key": "value"} where quotes confuse the count via one-sided braces); splitting a placeholder across lines; using single braces in text that needs them literal.

Common situations: Prompts embedding JSON/code samples with braces; typos in placeholders; copy-pasted markdown with stray '{' from formatting.

Related errors


AI-assisted analysis of OpenBB-finance/OpenBB@3e071fcc2c (2026-08-14). Data as JSON: /api/errors/5c4cf10535399ac3. Report an issue: GitHub.