huggingface/transformers · error · HTTPException
'input' must be a string or list
Error message
'input' must be a string or list
What it means
In the Responses-style API path, ResponseHandler reads body['input'] and accepts exactly two shapes: a plain string (treated as a single user message) or a list (either flat content items, or OpenAI Responses-style dicts with a 'role'). Any other JSON type — number, object, boolean, null — triggers HTTP 422 "'input' must be a string or list".
Source
Thrown at src/transformers/cli/serving/response.py:498
- **Multi-turn list** — messages and tool call items (``function_call``,
``function_call_output``) from a previous response, converted via
:meth:`_normalize_response_items`.
If ``instructions`` is present, it is prepended as a system message.
"""
inp = body["input"]
instructions = body.get("instructions")
if isinstance(inp, str):
messages = [{"role": "user", "content": inp}]
elif isinstance(inp, list):
if inp and "role" not in inp[0]:
# Flat content list (single-turn, e.g. input_text/input_image)
messages = [{"role": "user", "content": inp}]
else:
messages = ResponseHandler._normalize_response_items(inp)
else:
raise HTTPException(status_code=422, detail="'input' must be a string or list")
# Prepend instructions as a system message
if instructions:
if messages and messages[0]["role"] == "system":
messages[0]["content"] = instructions
else:
messages.insert(0, {"role": "system", "content": instructions})
return messages
@staticmethod
def _normalize_response_items(items: list[dict]) -> list[dict]:
"""Convert a list of Responses API items into chat messages.
Input items may be a mix of:
- Messages (``EasyInputMessageParam`` with ``role``, or ``type: "message"``).
- ``reasoning`` — buffered and attached as ``reasoning_content`` to the next assistant message.
- ``function_call`` — merged as ``tool_calls`` onto the preceding assistant message.View on GitHub (pinned to a597f97485)
Solutions
- Send input as a string: {"input": "Hello"}
- Or as a list: {"input": [{"type": "input_text", "text": "Hello"}]} or a list of role dicts
- Wrap object payloads into a single-item content list before sending
Example fix
# before
curl -X POST .../responses -d '{"model": "gpt2", "input": {"text": "hi"}}' # 422
# after
curl -X POST .../responses -d '{"model": "gpt2", "input": "hi"}' Defensive patterns
Strategy: type-guard
Validate before calling
inp = body.get("input")
if not isinstance(inp, (str, list)):
return JSONResponse(status_code=422, content={"error": "'input' must be a string or list"}) Type guard
def is_valid_input(inp) -> bool:
return isinstance(inp, (str, list)) Try / catch
resp = await client.post(url, json=body)
if resp.status_code == 422 and "must be a string or list" in resp.text:
body["input"] = str(body["input"])
resp = await client.post(url, json=body) Prevention
- Serialize input as str or list at the client
- Never send objects/null in the input field
- Use the official OpenAI client types to catch shape errors before shipping
When it happens
Trigger: POSTing {"input": 123} or {"input": {"text": "hi"}}; sending null when no input; a client SDK serializing the field to a non-array/object primitive; malformed JSON that decodes 'input' to a scalar.
Common situations: Migrating from OpenAI Responses API with an object-form input; missing the input field so a default scalar is injected; hand-rolled curl payloads with wrong types.
Related errors
- Unsupported input item type: {item_type!r}
- Missing `model` field in the request body.
- Unexpected fields in the request: {unexpected}
- Expected file upload, got string
- Expected model name as string
AI-assisted analysis of huggingface/transformers@a597f97485 (2026-08-14).
Data as JSON: /api/errors/2ddfaebde792f46b.
Report an issue: GitHub.