OpenBB-finance/OpenBB · error · ValueError
Prompt name '{v}' should be a valid identifier
Error message
Prompt name '{v}' should be a valid identifier What it means
Pydantic validation error on PromptConfigModel.name: the provided name (after strip) does not match ^[a-zA-Z_][a-zA-Z0-9_]*$, i.e. it is not identifier-like. Prompt names become tool/resource identifiers on the MCP server, so dashes, spaces, dots, and leading digits are rejected.
Source
Thrown at openbb_platform/extensions/mcp_server/openbb_mcp_server/models/mcp_config.py:127
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")
@classmethod
def validate_tags(cls, v: list[str]) -> list[str]:
"""Validate tags are non-empty strings."""
validated_tags = []
for tag in v:
if not isinstance(tag, str):
raise ValueError(f"Tag must be a string, got {type(tag)}")
if not tag.strip():
raise ValueError("Tag cannot be empty string")
validated_tags.append(tag.strip())
return validated_tags
class MCPConfigModel(BaseModel):
"""Model for validating the main MCP configuration structure."""View on GitHub (pinned to 3e071fcc2c)
Solutions
- Use snake_case identifiers: 'my-prompt' → 'my_prompt'.
- Start with a letter or underscore; strip file extensions and punctuation.
- Leave name unset to let the server auto-generate a valid one.
Example fix
# before
prompts:
- name: daily-report
content: "..."
# after
prompts:
- name: daily_report
content: "..." Defensive patterns
Strategy: validation
Validate before calling
import re
def prompt_name_or_none(name: str | None) -> str | None:
if name is None:
return None
n = re.sub(r"[^a-zA-Z0-9_]+", "_", name.strip()).strip("_")
n = f"_{n}" if n[:1].isdigit() else n
assert re.match(r"^[a-zA-Z_][a-zA-Z0-9_]*$", n), f"unusable name {name!r}"
return n Type guard
def is_identifier_like(name: str | None) -> bool:
return name is None or (bool(name.strip()) and bool(re.match(r"^[a-zA-Z_][a-zA-Z0-9_]*$", name.strip()))) Prevention
- Use snake_case prompt names; no hyphens, dots, spaces, or leading digits.
- Leave name unset to get a server-generated valid identifier.
- Sanitize names derived from titles or filenames at generation time.
When it happens
Trigger: Naming a prompt 'my-prompt', '1_greet', 'greet.me', or 'daily report' in the config; deriving names from human titles or file names with hyphens; non-ASCII names.
Common situations: Slugs with hyphens copied from URLs; prompts generated from markdown headings; names mirroring filenames like 'my-prompt.md'.
Related errors
- Prompt name cannot be empty string
- Argument name '{v}' must be a valid Python identifier
- Prompt content cannot be empty
- Unmatched braces in prompt content: {open_braces} opening, {
- Argument name cannot be empty
AI-assisted analysis of OpenBB-finance/OpenBB@3e071fcc2c (2026-08-14).
Data as JSON: /api/errors/167661425ce9553d.
Report an issue: GitHub.