BerriAI/litellm · error · TypeError
'models' must be a string or list of strings
Error message
'models' must be a string or list of strings
What it means
TypeError raised by litellm.batch_completion_models when the 'models' kwarg is neither a string, list, nor tuple — e.g. a dict, set, generator, or None. After popping 'models' from kwargs the function normalizes it (str -> [str], list/tuple -> list) and rejects anything else before building the ThreadPoolExecutor.
Source
Thrown at litellm/batch_completion/main.py:237
It sends requests concurrently and collects responses from all models that respond.
"""
import concurrent.futures
# ANSI escape codes for colored output
if "model" in kwargs:
kwargs.pop("model")
if "models" in kwargs:
models = kwargs.pop("models")
else:
raise Exception("'models' param not in kwargs")
if isinstance(models, str):
models = [models]
elif isinstance(models, (list, tuple)):
models = list(models)
else:
raise TypeError("'models' must be a string or list of strings")
if len(models) == 0:
return []
responses: Final = []
with concurrent.futures.ThreadPoolExecutor(max_workers=len(models)) as executor:
futures: Final = [executor.submit(litellm.completion, *args, model=model, **kwargs) for model in models]
for future in futures:
try:
result = future.result()
if result is not None:
responses.append(result)
except Exception as e:
print_verbose(f"batch_completion_models_all_responses: model request failed: {e}")
continue
View on GitHub (pinned to 6c2dcb801b)
Solutions
- Convert to a list first: models=list(models) for sets/generators/ranges.
- Guard against None: models=models or [] (note empty list returns [] quickly).
- For dicts, decide whether you meant the keys: models=list(models_dict.keys()).
Example fix
# before
litellm.batch_completion_models(models={"gpt-4o", "claude-3-5-sonnet"}, messages=[...])
# after
litellm.batch_completion_models(models=list({"gpt-4o", "claude-3-5-sonnet"}), messages=[...]) Defensive patterns
Strategy: type-guard
Validate before calling
models = kwargs.get("models")
if isinstance(models, (set, tuple, range)):
kwargs["models"] = list(models)
elif not isinstance(models, (str, list)):
raise TypeError("models must be str or list") Type guard
def is_valid_models_value(v) -> bool:
return isinstance(v, (str, list, tuple)) Prevention
- Normalize collections to list before passing.
- Reject None early in your own wrapper.
- Avoid generators for models — materialize them first.
When it happens
Trigger: Passing models as a set, dict, range, iterator, or None: litellm.batch_completion_models(models={'gpt-4o': 1}) or models=iter([...]). A single string is fine (wrapped into a list); other iterables like generators are not.
Common situations: Using a set for dedup and passing it straight through; passing a lazily-built generator from another function; a None leaking in from an optional config field.
Related errors
- Invalid value passed in for aget_assistants. Only bool or No
- Invalid value passed in for async_create_assistants. Only bo
- Invalid value passed in for async_delete_assistants. Only bo
- 'models' param not in kwargs
- input must be a string or a list
AI-assisted analysis of BerriAI/litellm@6c2dcb801b (2026-08-15).
Data as JSON: /api/errors/91a88058b6fe1abb.
Report an issue: GitHub.