{"record":{"id":"a6ea2b38d7e68254","repo":"oobabooga/textgen","slug":"functions-is-not-supported","errorCode":null,"errorMessage":"functions is not supported.","messagePattern":"functions is not supported\\.","errorType":"exception","errorClass":"InvalidRequestError","httpStatus":400,"severity":"error","filePath":"modules/api/completions.py","lineNumber":479,"sourceCode":"                # Mid-conversation system messages: preserve position in history\n                if current_message:\n                    chat_dialogue.append([current_message, '', '', {}])\n                    current_message = \"\"\n                chat_dialogue.append([content, '', '', {\"role\": \"system\"}])\n\n    if not user_input_last:\n        user_input = \"\"\n\n    return user_input, system_message, {\n        'internal': chat_dialogue,\n        'visible': copy.deepcopy(chat_dialogue),\n        'messages': history  # Store original messages for multimodal models\n    }\n\n\ndef chat_completions_common(body: dict, is_legacy: bool = False, stream=False, prompt_only=False, stop_event=None) -> dict:\n    if body.get('functions', []):\n        raise InvalidRequestError(message=\"functions is not supported.\", param='functions')\n\n    if body.get('function_call', ''):\n        raise InvalidRequestError(message=\"function_call is not supported.\", param='function_call')\n\n    if 'messages' not in body:\n        raise InvalidRequestError(message=\"messages is required\", param='messages')\n\n    tools = None\n    if 'tools' in body and body['tools'] is not None and isinstance(body['tools'], list) and body['tools']:\n        tools = validateTools(body['tools'])  # raises InvalidRequestError if validation fails\n\n    tool_choice = body.get('tool_choice', None)\n    if tool_choice == \"none\":\n        tools = None  # Disable tool detection entirely\n\n    messages = body['messages']\n    for m in messages:\n        if 'role' not in m:","sourceCodeStart":461,"sourceCodeEnd":497,"githubUrl":"https://github.com/oobabooga/textgen/blob/ed888c71f221df552750e1834b3654abab8ae345/modules/api/completions.py#L461-L497","documentation":"chat_completions_common rejects requests containing the legacy OpenAI 'functions' parameter. The backend supports the modern 'tools'/'tool_choice' API instead, so the legacy function-calling schema is explicitly rejected with an InvalidRequestError (HTTP 400) rather than silently ignored.","triggerScenarios":"POST /v1/chat/completions (or the legacy /v1/completions-style chat endpoint) with a non-empty 'functions' array in the JSON body, e.g. {\"model\": ..., \"messages\": [...], \"functions\": [{\"name\": \"get_weather\", \"parameters\": {...}}]}. Any truthy value for body['functions'] triggers it.","commonSituations":"Running old OpenAI SDK code (openai<1.0 style or tutorials predating 2023 tool-calling); porting a LangChain/LlamaIndex app that still emits 'functions'; SDK auto-injecting the param when a legacy function config is left in place.","solutions":["Migrate the request to the tools API: replace 'functions' with 'tools': [{\"type\": \"function\", \"function\": {\"name\": ..., \"description\": ..., \"parameters\": ...}}].","Replace 'function_call' with 'tool_choice' at the same time, since it is rejected too.","Upgrade old OpenAI SDK clients to openai>=1.0 and use client.chat.completions.create(tools=[...]) so the legacy param is never sent.","Remove leftover function configs from frameworks (e.g. LangChain agents) that emit the legacy field."],"exampleFix":"# before\nresp = client.chat.completions.create(\n    model=\"x\",\n    messages=msgs,\n    functions=[{\"name\": \"get_weather\", \"parameters\": {...}}],\n)\n\n# after\ntools = [{\"type\": \"function\", \"function\": {\"name\": \"get_weather\", \"description\": \"Get weather\", \"parameters\": {\"type\": \"object\", \"properties\": {\"city\": {\"type\": \"string\"}}, \"required\": [\"city\"]}}}]\nresp = client.chat.completions.create(\n    model=\"x\",\n    messages=msgs,\n    tools=tools,\n    tool_choice=\"auto\",\n)","handlingStrategy":"validation","validationCode":"def sanitize_chat_body(body: dict) -> dict:\n    body = dict(body)\n    body.pop('functions', None)   # or migrate to tools\n    body.pop('function_call', None)\n    return body","typeGuard":null,"tryCatchPattern":"try:\n    resp = client.chat.completions.create(**params)\nexcept openai.BadRequestError as e:\n    if 'functions is not supported' in str(e):\n        params = migrate_functions_to_tools(params)\n        resp = client.chat.completions.create(**params)\n    else:\n        raise","preventionTips":["Use openai>=1.0 SDK which never emits the legacy fields.","Search your codebase for 'functions=' and 'function_call=' in LLM calls before switching backends.","Keep an integration test that round-trips your request builder against the server."],"tags":["openai-api","chat-completions","function-calling","validation"],"backgroundTag":null,"analyzedSha":"ed888c71f221df552750e1834b3654abab8ae345","analyzedAt":"2026-08-15T05:24:21.000Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}