{"record":{"id":"8cecb80d89894194","repo":"BerriAI/litellm","slug":"prop-type-is-not-a-string","errorCode":null,"errorMessage":"Prop `type` is not a string","messagePattern":"Prop `type` is not a string","errorType":"exception","errorClass":"Exception","httpStatus":null,"severity":"error","filePath":"litellm/llms/bytez/chat/transformation.py","lineNumber":393,"sourceCode":"}\n\n\ndef adapt_messages_to_bytez_standard(messages: list[dict]):\n    messages = _adapt_string_only_content_to_lists(messages)\n\n    new_messages: Final = []\n\n    for message in messages:\n        role = message[\"role\"]\n        content: list = message[\"content\"]\n\n        new_content = []\n\n        for content_item in content:\n            type: str | None = content_item.get(\"type\")\n\n            if not type:\n                raise Exception(\"Prop `type` is not a string\")\n\n            content_item_map = open_ai_to_bytez_content_item_map[type]\n\n            if not content_item_map:\n                raise Exception(f\"Prop `{type}` is not supported\")\n\n            new_type = content_item_map[\"type\"]\n\n            value_name = content_item_map[\"value_name\"]\n\n            value: str | None = content_item.get(value_name)\n\n            if not value:\n                raise Exception(f\"Prop `{value_name}` is not a string\")\n\n            new_content.append({\"type\": new_type, value_name: value})\n\n        new_messages.append({\"role\": role, \"content\": new_content})","sourceCodeStart":375,"sourceCodeEnd":411,"githubUrl":"https://github.com/BerriAI/litellm/blob/77b7c6c40c0c5aa5fbcb1d6a1825ac39ca8829b8/litellm/llms/bytez/chat/transformation.py#L375-L411","documentation":"Before sending messages to Bytez, LiteLLM normalizes each content part; this guard fires when a content-part dict has no 'type' key or a falsy 'type' (empty string/None). Every part must carry a non-empty type string so it can be looked up in open_ai_to_bytez_content_item_map.","triggerScenarios":"A message like {\"role\": \"user\", \"content\": [{\"text\": \"hi\"}]} (missing type), or {\"type\": \"\", \"text\": \"hi\"}; programmatically built parts where the type field was dropped; mixing raw strings inside a dict part by mistake.","commonSituations":"Hand-rolled prompt assemblers; parts produced by another SDK with different casing (e.g. 'kind' instead of 'type'); data corruption or empty dicts slipping into content lists.","solutions":["Give every content part a valid 'type' (\"text\", \"image_url\", \"input_audio\", \"video_url\").","Validate parts with a small helper before calling bytez models.","When wrapping plain strings, let litellm normalize by using a plain string content or {\"type\":\"text\",\"text\":...}."],"exampleFix":"# before\nmessages = [{\"role\": \"user\", \"content\": [{\"text\": \"hi\"}]}]\n\n# after\nmessages = [{\"role\": \"user\", \"content\": [{\"type\": \"text\", \"text\": \"hi\"}]}]","handlingStrategy":"validation","validationCode":"def content_parts_valid(content: list) -> bool:\n    return all(\n        isinstance(p, dict) and isinstance(p.get(\"type\"), str) and p[\"type\"]\n        for p in content\n    )","typeGuard":"def is_typed_content_part(part: object) -> bool:\n    return isinstance(part, dict) and isinstance(part.get(\"type\"), str) and len(part[\"type\"]) > 0","tryCatchPattern":"try:\n    litellm.completion(model=\"bytez/org/model\", messages=messages)\nexcept Exception as e:\n    if \"`type` is not a string\" in str(e):\n        messages = normalize_parts(messages)  # ensure every part has a type\n        litellm.completion(model=\"bytez/org/model\", messages=messages)\n    else:\n        raise","preventionTips":["Always emit parts through a builder that sets 'type' explicitly.","Never splice optional dicts into content without checking for the 'type' key."],"tags":["bytez","messages","content-parts","validation"],"backgroundTag":"invalid-content-part","analyzedSha":"77b7c6c40c0c5aa5fbcb1d6a1825ac39ca8829b8","analyzedAt":"2026-08-18T11:44:31.656Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}