OpenBB-finance/OpenBB · error · ValueError

Argument name '{v}' must be a valid Python identifier

Error message

Argument name '{v}' must be a valid Python identifier

What it means

Pydantic validation error on ArgumentDefinitionModel.name: the name fails the regex ^[a-zA-Z_][a-zA-Z0-9_]*$ — it must be a valid Python identifier. Names are used as Python kwargs and template placeholders, so dashes, spaces, leading digits, or unicode characters are rejected at config load time.

Source

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

    """Model for validating prompt argument definitions."""

    name: str = Field(..., description="Name of the argument")
    type: str = Field(default="str", description="Type of the argument")
    default: Any | None = Field(
        default=None, description="Default value for the argument"
    )
    description: str | None = Field(
        default=None, description="Description of the argument"
    )

    @field_validator("name")
    @classmethod
    def validate_name(cls, v: str) -> str:
        """Validate argument name is a valid identifier."""
        if not v:
            raise ValueError("Argument name cannot be empty")
        if not re.match(r"^[a-zA-Z_][a-zA-Z0-9_]*$", v):
            raise ValueError(f"Argument name '{v}' must be a valid Python identifier")
        return v

    @field_validator("type")
    @classmethod
    def validate_type(cls, v: str) -> str:
        """Validate type is a recognized type string."""
        valid_types = {
            "str",
            "string",
            "int",
            "integer",
            "float",
            "bool",
            "boolean",
            "list",
            "dict",
            "any",
            "Any",

View on GitHub (pinned to 3e071fcc2c)

Solutions

  1. Rename the argument to snake_case: 'start-date' → 'start_date'.
  2. Start the name with a letter or underscore, never a digit.
  3. Use only [a-zA-Z0-9_] characters after the first character.

Example fix

# before
arguments:
  - name: start-date
    type: str

# after
arguments:
  - name: start_date
    type: str
Defensive patterns

Strategy: validation

Validate before calling

import re

IDENT = re.compile(r"^[a-zA-Z_][a-zA-Z0-9_]*$")

def normalize_arg_name(name: str) -> str:
    snake = re.sub(r"[^a-zA-Z0-9_]+", "_", name.strip()).strip("_")
    if not snake or snake[0].isdigit():
        snake = f"_{snake}"
    if not IDENT.match(snake):
        raise ValueError(f"cannot normalize {name!r}")
    return snake

Type guard

def is_identifier(name: str) -> bool:
    return isinstance(name, str) and bool(re.match(r"^[a-zA-Z_][a-zA-Z0-9_]*$", name))

Prevention

When it happens

Trigger: Naming an argument 'start-date', '1st_arg', 'stock symbol', or 'café' in an MCP config; converting a CLI flag (--start-date) directly into an argument name without normalizing; JSON configs generated from user-facing labels.

Common situations: Configs authored from REST query-parameter names that contain hyphens; migrating configs between tools with different naming rules; non-ASCII names from localized configs.

Related errors


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