BerriAI/litellm · error · ValueError
`prompt` must be a non-empty string or a non-empty list of s
Error message
`prompt` must be a non-empty string or a non-empty list of strings. Got: {prompt_type_name}. What it means
This ValueError comes from LiteLLM's chat-endpoint input normalization: when you pass a bare `prompt` (instead of `messages`) it must be a non-empty string or a non-empty list of non-empty strings. Pre-tokenized prompts (list[int]/list[list[int]]) are deliberately rejected because only OpenAI-family text endpoints accept them. Anything else (None, empty string, empty list, mixed types, ints) fails fast here.
Source
Thrown at litellm/litellm_core_utils/prompt_templates/common_utils.py:1878
def text_completion_prompt_to_messages(prompt: object) -> tuple[AllMessageValues, ...]:
"""
Wrap an OpenAI ``/v1/completions`` ``prompt`` into Chat Completion messages.
Mirrors what ``litellm.text_completion`` does on the real-time path: a
string becomes a single user message, and a list of strings becomes one
user message per element. Pre-tokenized prompts (``list[int]`` /
``list[list[int]]``) are only meaningful for the OpenAI-family text
endpoints, so they are rejected here rather than silently forwarded, as is
an empty prompt, which every chat-shaped provider rejects downstream.
"""
prompt_type_name: Final = type(prompt).__name__
if isinstance(prompt, str) and prompt:
return (ChatCompletionUserMessage(role="user", content=prompt),)
entries: Final = cast("Sequence[object]", prompt) if isinstance(prompt, Sequence) else ()
string_entries: Final = tuple(entry for entry in entries if isinstance(entry, str) and entry)
if string_entries and len(string_entries) == len(entries):
return tuple(ChatCompletionUserMessage(role="user", content=entry) for entry in string_entries)
raise ValueError(f"`prompt` must be a non-empty string or a non-empty list of strings. Got: {prompt_type_name}.")
View on GitHub (pinned to 6c2dcb801b)
Solutions
- Pass a non-empty prompt: validate/strip the string and supply a default (e.g. '.') when it is empty
- Use the messages=[{"role": "user", "content": ...}] API instead of prompt= for chat models
- For token-ID prompts, use an OpenAI-family text completion endpoint, not the chat path
Example fix
# before
resp = litellm.completion(model="gpt-4o-mini", prompt=user_text) # user_text may be ""
# after
user_text = user_text.strip() or "."
resp = litellm.completion(model="gpt-4o-mini", messages=[{"role": "user", "content": user_text}]) Defensive patterns
Strategy: validation
Validate before calling
def normalize_prompt(prompt):
if isinstance(prompt, str) and prompt.strip():
return [{"role": "user", "content": prompt}]
if isinstance(prompt, list) and prompt and all(isinstance(p, str) and p.strip() for p in prompt):
return [{"role": "user", "content": p} for p in prompt]
raise ValueError("prompt must be a non-empty string or non-empty list of non-empty strings")
messages = normalize_prompt(user_input) Type guard
from typing import Any
def is_valid_prompt(p: Any) -> bool:
if isinstance(p, str):
return bool(p.strip())
if isinstance(p, list):
return bool(p) and all(isinstance(x, str) and x.strip() for x in p)
return False Prevention
- Prefer the messages=[...] API over prompt= for chat models
- Strip and default-empty user input before building requests
- Never pass token IDs (list[int]) to chat-shaped endpoints
When it happens
Trigger: Calling a chat-shaped completion (e.g. litellm.completion or a provider chat handler) with prompt="", prompt=[], prompt=["hi", ""], prompt=None, or prompt=[1,2,3] instead of using the messages= parameter with proper role objects.
Common situations: Porting code from OpenAI's legacy completions API (prompt=...) to a chat model; dynamic prompts that are empty after template substitution or stripping; accidentally passing token IDs from a tokenizer to a chat endpoint.
Related errors
- input is required
- Amazon Nova Canvas {task_type} requires a text prompt. Pass
- kwarg `messages` must be an array of messages that follow th
- Invalid mode: {custom_auth_settings['mode']}
- Filtering by 'provider' is not supported when using managed
AI-assisted analysis of BerriAI/litellm@6c2dcb801b (2026-08-15).
Data as JSON: /api/errors/cc2d0c23ed3491d1.
Report an issue: GitHub.