{"record":{"id":"cc2d0c23ed3491d1","repo":"BerriAI/litellm","slug":"prompt-must-be-a-non-empty-string-or-a-non-empty","errorCode":null,"errorMessage":"`prompt` must be a non-empty string or a non-empty list of strings. Got: {prompt_type_name}.","messagePattern":"`prompt` must be a non-empty string or a non-empty list of strings\\. Got: (.+?)\\.","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"litellm/litellm_core_utils/prompt_templates/common_utils.py","lineNumber":1878,"sourceCode":"def text_completion_prompt_to_messages(prompt: object) -> tuple[AllMessageValues, ...]:\n    \"\"\"\n    Wrap an OpenAI ``/v1/completions`` ``prompt`` into Chat Completion messages.\n\n    Mirrors what ``litellm.text_completion`` does on the real-time path: a\n    string becomes a single user message, and a list of strings becomes one\n    user message per element. Pre-tokenized prompts (``list[int]`` /\n    ``list[list[int]]``) are only meaningful for the OpenAI-family text\n    endpoints, so they are rejected here rather than silently forwarded, as is\n    an empty prompt, which every chat-shaped provider rejects downstream.\n    \"\"\"\n    prompt_type_name: Final = type(prompt).__name__\n    if isinstance(prompt, str) and prompt:\n        return (ChatCompletionUserMessage(role=\"user\", content=prompt),)\n    entries: Final = cast(\"Sequence[object]\", prompt) if isinstance(prompt, Sequence) else ()\n    string_entries: Final = tuple(entry for entry in entries if isinstance(entry, str) and entry)\n    if string_entries and len(string_entries) == len(entries):\n        return tuple(ChatCompletionUserMessage(role=\"user\", content=entry) for entry in string_entries)\n    raise ValueError(f\"`prompt` must be a non-empty string or a non-empty list of strings. Got: {prompt_type_name}.\")\n","sourceCodeStart":1860,"sourceCodeEnd":1879,"githubUrl":"https://github.com/BerriAI/litellm/blob/77b7c6c40c0c5aa5fbcb1d6a1825ac39ca8829b8/litellm/litellm_core_utils/prompt_templates/common_utils.py#L1860-L1879","documentation":"When routing a completion-style prompt to a chat-shaped provider, litellm converts it into user messages. It accepts only a non-empty string or a list of non-empty strings; pre-tokenized prompts (list[int] / list[list[int]]) are rejected because they only make sense for OpenAI-family text endpoints, as are empty values which every chat provider rejects downstream.","triggerScenarios":"Calling with prompt='' or prompt=[], prompt=[1, 2, 3] (token ids), or a list that mixes strings with non-string entries such that string_entries != entries.","commonSituations":"Porting completion code that used token arrays to a chat model; passing None or '' when user input is empty; dynamically built prompts that end up blank.","solutions":["Pass a non-empty string, or a list where every element is a non-empty string","For token-id prompts, use the OpenAI-family text completion endpoints instead of chat","Guard upstream: replace empty prompts with a placeholder like '.' or reject them in your handler"],"exampleFix":"# before\nlitellm.completion(model=\"gpt-4o-mini\", prompt=[])\nlitellm.completion(model=\"gpt-4o-mini\", prompt=[101, 102])\n\n# after\nlitellm.completion(model=\"gpt-4o-mini\", prompt=\"Hello\")\nlitellm.completion(model=\"gpt-4o-mini\", prompt=[\"Hello\", \"world\"])","handlingStrategy":"type-guard","validationCode":"from typing import Sequence\n\ndef normalize_prompt(prompt):\n    \"\"\"Return a chat-safe prompt or None if unusable.\"\"\"\n    if isinstance(prompt, str) and prompt.strip():\n        return prompt\n    if isinstance(prompt, Sequence) and not isinstance(prompt, (str, bytes)):\n        if all(isinstance(x, str) and x.strip() for x in prompt) and len(prompt) > 0:\n            return list(prompt)\n    return None\n\n# safe_prompt = normalize_prompt(prompt)\n# if safe_prompt is None: reject/handle before calling litellm","typeGuard":"from collections.abc import Sequence\nfrom typing import TypeGuard\n\ndef is_valid_chat_prompt(prompt: object) -> TypeGuard[str | list[str]]:\n    if isinstance(prompt, str):\n        return bool(prompt)\n    if isinstance(prompt, Sequence) and not isinstance(prompt, (str, bytes)):\n        return bool(prompt) and all(isinstance(p, str) and p for p in prompt)\n    return False","tryCatchPattern":"try:\n    litellm.completion(model=model, prompt=prompt)\nexcept ValueError as e:\n    if \"must be a non-empty string\" in str(e):\n        prompt = \".\"  # or reject the request upstream\n    else:\n        raise","preventionTips":["Never forward token-id arrays to chat-shaped models; route them to text completion endpoints","Default empty user input to a placeholder or reject it at the API boundary","Unit-test prompt normalization for '', [], [1, 2], ['a', None] inputs"],"tags":["prompt","validation","request-format"],"backgroundTag":"invalid-request-parameter","analyzedSha":"77b7c6c40c0c5aa5fbcb1d6a1825ac39ca8829b8","analyzedAt":"2026-08-18T11:44:31.656Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}