microsoft/autogen · error · ValueError

Invalid name: {name}. Only letters, numbers, '_' and '-' are

Error message

Invalid name: {name}. Only letters, numbers, '_' and '-' are allowed.

What it means

assert_valid_name() enforces that user-configured names match ^[a-zA-Z0-9_-]+$ — at least one character, only letters, digits, underscore, hyphen — and raises ValueError otherwise. Per its docstring it is for validating user configuration (contrast _normalize_name, which munges LLM output). In the Ollama client it guards tool names before they are sent to the server.

Source

Thrown at python/packages/autogen-ext/src/autogen_ext/models/ollama/_ollama_client.py:367


def normalize_name(name: str) -> str:
    """
    LLMs sometimes ask functions while ignoring their own format requirements, this function should be used to replace invalid characters with "_".

    Prefer _assert_valid_name for validating user configuration or input
    """
    return re.sub(r"[^a-zA-Z0-9_-]", "_", name)[:64]


def assert_valid_name(name: str) -> str:
    """
    Ensure that configured names are valid, raises ValueError if not.

    For munging LLM responses use _normalize_name to ensure LLM specified names don't break the API.
    """
    if not re.match(r"^[a-zA-Z0-9_-]+$", name):
        raise ValueError(f"Invalid name: {name}. Only letters, numbers, '_' and '-' are allowed.")
    if len(name) > 64:
        raise ValueError(f"Invalid name: {name}. Name must be less than 64 characters.")
    return name


# TODO: Does this need to change?
def normalize_stop_reason(stop_reason: str | None) -> FinishReasons:
    if stop_reason is None:
        return "unknown"

    # Convert to lower case
    stop_reason = stop_reason.lower()

    KNOWN_STOP_MAPPINGS: Dict[str, FinishReasons] = {
        "stop": "stop",
        "end_turn": "stop",
        "tool_calls": "function_calls",
    }

View on GitHub (pinned to 027ecf0a37)

Solutions

  1. Rename the tool/function to use only [a-zA-Z0-9_-], e.g. get_weather instead of get.weather
  2. If the name comes from an LLM response, use the module's _normalize_name() to sanitize it instead of asserting
  3. Validate names at registration time so the failure surfaces before any model call

Example fix

# before
tool = FunctionTool(func=fn, name="fetch.stock.price")

# after
tool = FunctionTool(func=fn, name="fetch_stock_price")
Defensive patterns

Strategy: validation

Validate before calling

import re

def check_name(name: str) -> bool:
    return bool(re.fullmatch(r"[a-zA-Z0-9_-]+", name)) and len(name) <= 64

if not check_name(tool.name):
    tool = tool.model_copy(update={"name": re.sub(r"[^a-zA-Z0-9_-]", "_", tool.name)[:64]})

Type guard

def is_valid_name(name: str) -> bool:
    return bool(re.fullmatch(r"[a-zA-Z0-9_-]{1,64}", name))

Try / catch

try:
    assert_valid_name(name)
except ValueError:
    name = re.sub(r"[^a-zA-Z0-9_-]", "_", name)[:64]

Prevention

When it happens

Trigger: Registering a tool whose name contains a space, dot, slash, or other symbol (e.g. 'get.weather', 'search/query'); an empty name; a name with unicode characters; a tool name auto-generated from a function with mangled characters.

Common situations: Deriving tool names from natural-language labels or file names; multi-language function names; copy-pasting OpenAI function names that Ollama rejects.

Related errors


AI-assisted analysis of microsoft/autogen@027ecf0a37 (2026-08-15). Data as JSON: /api/errors/79081d05da761815. Report an issue: GitHub.