oobabooga/textgen · error · InvalidRequestError

role: function is not supported.

Error message

role: function is not supported.

What it means

Messages with role 'function' (the legacy OpenAI mechanism for returning tool results) are rejected. The backend implements the modern tools API where results come back as role 'tool' messages with a 'tool_call_id', so the legacy role is explicitly refused with InvalidRequestError (400).

Source

Thrown at modules/api/completions.py:500

        raise InvalidRequestError(message="function_call is not supported.", param='function_call')

    if 'messages' not in body:
        raise InvalidRequestError(message="messages is required", param='messages')

    tools = None
    if 'tools' in body and body['tools'] is not None and isinstance(body['tools'], list) and body['tools']:
        tools = validateTools(body['tools'])  # raises InvalidRequestError if validation fails

    tool_choice = body.get('tool_choice', None)
    if tool_choice == "none":
        tools = None  # Disable tool detection entirely

    messages = body['messages']
    for m in messages:
        if 'role' not in m:
            raise InvalidRequestError(message="messages: missing role", param='messages')
        elif m['role'] == 'function':
            raise InvalidRequestError(message="role: function is not supported.", param='messages')

        # Handle multimodal content validation
        content = m.get('content')
        if content is None:
            # OpenAI allows content: null on assistant messages when tool_calls is present
            if m['role'] == 'assistant' and m.get('tool_calls'):
                m['content'] = ''
            else:
                raise InvalidRequestError(message="messages: missing content", param='messages')

        # Validate multimodal content structure
        if isinstance(content, list):
            for item in content:
                if not isinstance(item, dict) or 'type' not in item:
                    raise InvalidRequestError(message="messages: invalid content item format", param='messages')
                if item['type'] not in ['text', 'image_url']:
                    raise InvalidRequestError(message="messages: unsupported content type", param='messages')
                if item['type'] == 'text' and 'text' not in item:

View on GitHub (pinned to ed888c71f2)

Solutions

  1. Convert function results to the modern form: {"role": "tool", "tool_call_id": <id from assistant tool_calls>, "content": <result>}.
  2. Upgrade to the modern loop: assistant message carries 'tool_calls', the tool reply uses role 'tool'.
  3. Upgrade the OpenAI SDK to >=1.0, which emits role 'tool' natively.

Example fix

# before
messages.append({"role": "function", "name": "get_weather", "content": "21C"})

# after
messages.append({"role": "tool", "tool_call_id": assistant_msg["tool_calls"][0]["id"], "content": "21C"})
Defensive patterns

Strategy: validation

Validate before calling

def migrate_function_roles(messages):
    out = []
    for m in messages:
        if m.get('role') == 'function':
            out.append({'role': 'tool', 'tool_call_id': m.get('tool_call_id', m.get('name', 'call_0')), 'content': m.get('content', '')})
        else:
            out.append(m)
    return out

Type guard

def has_legacy_function_role(messages) -> bool:
    return any(isinstance(m, dict) and m.get('role') == 'function' for m in messages)

Try / catch

try:
    resp = client.chat.completions.create(model=m, messages=msgs)
except openai.BadRequestError as e:
    if 'role: function is not supported' in str(e):
        msgs = migrate_function_roles(msgs)
        resp = client.chat.completions.create(model=m, messages=msgs)
    else:
        raise

Prevention

When it happens

Trigger: POST /v1/chat/completions with a message {"role": "function", "name": "get_weather", "content": "..."}. Typically sent by old OpenAI SDK versions after executing a function call, or by hand-rolled agent loops following 2023 tutorials.

Common situations: Old openai<1.0 SDK chat loops; agent frameworks not yet migrated to the tools API; mixing a legacy client with the modern backend after fixing only 'functions'/'function_call'.

Related errors


AI-assisted analysis of oobabooga/textgen@ed888c71f2 (2026-08-15). Data as JSON: /api/errors/fc3ccd8c50f53db6. Report an issue: GitHub.