BerriAI/litellm · error · Exception

Prop `{value_name}` is not a string

Error message

Prop `{value_name}` is not a string

What it means

Thrown by the Bytez adapter when a mapped content item is missing its value field (e.g. a `text` item without `text`, an `image_url` item without `url`). The adapter looks up which property to read via `value_name` and refuses empty/missing values. Despite the wording, it fires for any falsy value (None, empty string), not just non-string types.

Source

Thrown at litellm/llms/bytez/chat/transformation.py:407

        for content_item in content:
            type: str | None = content_item.get("type")

            if not type:
                raise Exception("Prop `type` is not a string")

            content_item_map = open_ai_to_bytez_content_item_map[type]

            if not content_item_map:
                raise Exception(f"Prop `{type}` is not supported")

            new_type = content_item_map["type"]

            value_name = content_item_map["value_name"]

            value: str | None = content_item.get(value_name)

            if not value:
                raise Exception(f"Prop `{value_name}` is not a string")

            new_content.append({"type": new_type, value_name: value})

        new_messages.append({"role": role, "content": new_content})

    return new_messages


# "content": "The cat ran so fast"
# becomes
# "content": [{"type": "text", "text": "The cat ran so fast"}]
def _adapt_string_only_content_to_lists(messages: list[dict]):
    new_messages: Final = []

    for message in messages:
        role = message.get("role")
        content = message.get("content")

View on GitHub (pinned to 6c2dcb801b)

Solutions

  1. Ensure each content item carries a non-empty value under the expected key: `text` for text, `url` for image_url/input_audio/video_url.
  2. Flatten nested OpenAI structures before sending: `{"type": "image_url", "url": "https://..."}` instead of `{"type": "image_url", "image_url": {"url": ...}}`.
  3. Add a pre-flight validator that rejects content items whose mapped value key is missing or empty.
  4. Log the offending message before the call to identify which part is malformed.

Example fix

// before
content = [{"type": "image_url", "image_url": {"url": "https://x/y.png"}}]

// after (value read directly from `url` key)
content = [{"type": "image_url", "url": "https://x/y.png"}]
Defensive patterns

Strategy: validation

Validate before calling

VALUE_KEY = {"text": "text", "image_url": "url", "input_audio": "url", "video_url": "url"}

def validate_bytez_content_values(content):
    for part in content:
        key = VALUE_KEY.get(part.get("type"))
        if key and not part.get(key):
            raise ValueError(f"content part of type {part['type']} missing non-empty '{key}'")

Type guard

def has_bytez_value(part) -> bool:
    key = {"text": "text", "image_url": "url", "input_audio": "url", "video_url": "url"}.get(part.get("type"))
    return key is not None and isinstance(part.get(key), str) and bool(part[key].strip())

Prevention

When it happens

Trigger: Sending `{"type": "image_url"}` with no `url` key, `{"type": "text", "text": ""}`, or `{"type": "input_audio", "input_audio": {...}}` (wrong nesting — the adapter expects the value directly under the mapped key, e.g. `url`). Note `image_url` items must have `url` as a plain string sibling of `type`, and `text` items must have a non-empty `text`.

Common situations: Generating content parts dynamically and leaving fields empty; misunderstanding that Bytez expects `{"type": "image", "url": ...}`-shaped input rather than OpenAI's nested `{"image_url": {"url": ...}}` (the map reads `content_item.get("url")` directly); whitespace-only strings pass but empty strings fail.

Related errors


AI-assisted analysis of BerriAI/litellm@6c2dcb801b (2026-08-15). Data as JSON: /api/errors/86f7c42c4f125070. Report an issue: GitHub.