oobabooga/textgen · error · InvalidRequestError

messages: unsupported content type

Error message

messages: unsupported content type

What it means

In multimodal content lists, only item types 'text' and 'image_url' are accepted. Any other 'type' value (e.g. 'image', 'audio', 'input_audio', 'video') raises InvalidRequestError (400, param='messages').

Source

Thrown at modules/api/completions.py:517

        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:
                    raise InvalidRequestError(message="messages: missing text in content item", param='messages')
                if item['type'] == 'image_url' and ('image_url' not in item or 'url' not in item['image_url']):
                    raise InvalidRequestError(message="messages: missing image_url in content item", param='messages')

    # Chat Completions
    object_type = 'chat.completion' if not stream else 'chat.completion.chunk'
    created_time = int(time.time())
    cmpl_id = "chatcmpl-%d" % (int(time.time() * 1000000000))
    resp_list = 'data' if is_legacy else 'choices'

    # generation parameters
    generate_params = process_parameters(body, is_legacy=is_legacy)
    if stop_event is not None:
        generate_params['stop_event'] = stop_event
    continue_ = body['continue_']

    # Instruction template

View on GitHub (pinned to ed888c71f2)

Solutions

  1. Convert to OpenAI vision format: {"type": "image_url", "image_url": {"url": <url or data: URI>}}.
  2. Strip unsupported content types (audio/refusal/etc.) before sending.
  3. Ensure a multimodal (llava/multimodal-projector) model is actually loaded if you want image inputs to work downstream.

Example fix

# before
{"type": "image", "source": {"type": "base64", "media_type": "image/png", "data": b64}}

# after
{"type": "image_url", "image_url": {"url": "data:image/png;base64," + b64}}
Defensive patterns

Strategy: validation

Validate before calling

ALLOWED = {'text', 'image_url'}

def strip_unsupported_types(content):
    if isinstance(content, str):
        return content
    return [i for i in content if isinstance(i, dict) and i.get('type') in ALLOWED]

Type guard

def has_supported_types(content) -> bool:
    return isinstance(content, str) or all(isinstance(i, dict) and i.get('type') in ('text', 'image_url') for i in content)

Try / catch

try:
    resp = client.chat.completions.create(model=m, messages=msgs)
except openai.BadRequestError as e:
    if 'unsupported content type' in str(e):
        msgs = [{'role': r['role'], 'content': strip_unsupported_types(r['content']) if isinstance(r.get('content'), list) else r.get('content')} for r in msgs]
        resp = client.chat.completions.create(model=m, messages=msgs)
    else:
        raise

Prevention

When it happens

Trigger: POST /v1/chat/completions with a content item like {"type": "image", "source": ...} (Anthropic style), {"type": "audio", ...}, or {"type": "refusal"}.

Common situations: Porting Anthropic Messages API payloads ('type': 'image' with 'source') to this OpenAI-compatible server; using newer OpenAI audio content types this backend never implemented; typos like 'imageURL'.

Related errors


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