{"record":{"id":"79081d05da761815","repo":"microsoft/autogen","slug":"invalid-name-name-only-letters-numbers-a-79081d","errorCode":null,"errorMessage":"Invalid name: {name}. Only letters, numbers, '_' and '-' are allowed.","messagePattern":"Invalid name: (.+?)\\. Only letters, numbers, '_' and '-' are allowed\\.","errorType":"exception","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"python/packages/autogen-ext/src/autogen_ext/models/ollama/_ollama_client.py","lineNumber":367,"sourceCode":"\n\ndef normalize_name(name: str) -> str:\n    \"\"\"\n    LLMs sometimes ask functions while ignoring their own format requirements, this function should be used to replace invalid characters with \"_\".\n\n    Prefer _assert_valid_name for validating user configuration or input\n    \"\"\"\n    return re.sub(r\"[^a-zA-Z0-9_-]\", \"_\", name)[:64]\n\n\ndef assert_valid_name(name: str) -> str:\n    \"\"\"\n    Ensure that configured names are valid, raises ValueError if not.\n\n    For munging LLM responses use _normalize_name to ensure LLM specified names don't break the API.\n    \"\"\"\n    if not re.match(r\"^[a-zA-Z0-9_-]+$\", name):\n        raise ValueError(f\"Invalid name: {name}. Only letters, numbers, '_' and '-' are allowed.\")\n    if len(name) > 64:\n        raise ValueError(f\"Invalid name: {name}. Name must be less than 64 characters.\")\n    return name\n\n\n# TODO: Does this need to change?\ndef normalize_stop_reason(stop_reason: str | None) -> FinishReasons:\n    if stop_reason is None:\n        return \"unknown\"\n\n    # Convert to lower case\n    stop_reason = stop_reason.lower()\n\n    KNOWN_STOP_MAPPINGS: Dict[str, FinishReasons] = {\n        \"stop\": \"stop\",\n        \"end_turn\": \"stop\",\n        \"tool_calls\": \"function_calls\",\n    }","sourceCodeStart":349,"sourceCodeEnd":385,"githubUrl":"https://github.com/microsoft/autogen/blob/027ecf0a379bcc1d09956d46d12d44a3ad9cee14/python/packages/autogen-ext/src/autogen_ext/models/ollama/_ollama_client.py#L349-L385","documentation":"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.","triggerScenarios":"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.","commonSituations":"Deriving tool names from natural-language labels or file names; multi-language function names; copy-pasting OpenAI function names that Ollama rejects.","solutions":["Rename the tool/function to use only [a-zA-Z0-9_-], e.g. get_weather instead of get.weather","If the name comes from an LLM response, use the module's _normalize_name() to sanitize it instead of asserting","Validate names at registration time so the failure surfaces before any model call"],"exampleFix":"# before\ntool = FunctionTool(func=fn, name=\"fetch.stock.price\")\n\n# after\ntool = FunctionTool(func=fn, name=\"fetch_stock_price\")","handlingStrategy":"validation","validationCode":"import re\n\ndef check_name(name: str) -> bool:\n    return bool(re.fullmatch(r\"[a-zA-Z0-9_-]+\", name)) and len(name) <= 64\n\nif not check_name(tool.name):\n    tool = tool.model_copy(update={\"name\": re.sub(r\"[^a-zA-Z0-9_-]\", \"_\", tool.name)[:64]})","typeGuard":"def is_valid_name(name: str) -> bool:\n    return bool(re.fullmatch(r\"[a-zA-Z0-9_-]{1,64}\", name))","tryCatchPattern":"try:\n    assert_valid_name(name)\nexcept ValueError:\n    name = re.sub(r\"[^a-zA-Z0-9_-]\", \"_\", name)[:64]","preventionTips":["Use assert_valid_name for user config and _normalize_name for LLM-generated names — matching the module's own contract","Validate tool names at registration, not at model-call time","Generate names from a constrained alphabet (slugify) rather than free text"],"tags":["ollama","tool-calling","naming","validation"],"backgroundTag":null,"analyzedSha":"027ecf0a379bcc1d09956d46d12d44a3ad9cee14","analyzedAt":"2026-08-15T03:38:00.719Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}