hiyouga/LlamaFactory · error · HTTPException
Invalid tools
Error message
Invalid tools
What it means
Raised as HTTP 400 when the request includes a non-empty tools array but serializing each tool's .function via dictify() raises json.JSONDecodeError. In practice this means a tool definition is malformed enough that its function object cannot be dictified and dumped — e.g. custom/non-FunctionTool objects or arguments already containing broken JSON.
Source
Thrown at src/llamafactory/api/chat.py:174
check_ssrf_url(audio_url)
audio_stream = requests.get(audio_url, stream=True).raw
audios.append(audio_stream)
else:
raise HTTPException(
status_code=status.HTTP_400_BAD_REQUEST, detail=f"Invalid input type {input_item.type}."
)
input_messages.append({"role": ROLE_MAPPING[message.role], "content": text_content})
else:
input_messages.append({"role": ROLE_MAPPING[message.role], "content": message.content})
tool_list = request.tools
if isinstance(tool_list, list) and len(tool_list):
try:
tools = json.dumps([dictify(tool.function) for tool in tool_list], ensure_ascii=False)
except json.JSONDecodeError:
raise HTTPException(status_code=status.HTTP_400_BAD_REQUEST, detail="Invalid tools")
else:
tools = None
return input_messages, system, tools, images or None, videos or None, audios or None
def _create_stream_chat_completion_chunk(
completion_id: str,
model: str,
delta: "ChatCompletionMessage",
index: Optional[int] = 0,
finish_reason: Optional["Finish"] = None,
) -> str:
choice_data = ChatCompletionStreamResponseChoice(index=index, delta=delta, finish_reason=finish_reason)
chunk = ChatCompletionStreamResponse(id=completion_id, model=model, choices=[choice_data])
return jsonify(chunk)
View on GitHub (pinned to f28afaf635)
Solutions
- Ensure each tool is {type: 'function', function: {name, description?, parameters (JSON schema)}}.
- Validate each tool with json.dumps(tool.function) client-side before sending; if it throws, fix the object.
- Do not confuse tools (definitions) with messages containing role 'tool' (results) — only send definitions in tools.
- Simplify to a single minimal tool and re-add tools one by one to find the malformed entry.
Example fix
// before
tools: [{ name: 'get_weather', parameters: {type:'object'} }] // missing function wrapper
// after
tools: [{
type: 'function',
function: { name: 'get_weather', description: 'Get weather', parameters: {type:'object', properties:{city:{type:'string'}}, required:['city']} }
}] Defensive patterns
Strategy: validation
Validate before calling
import json
def tools_serializable(tools):
if not tools:
return True
try:
for t in tools:
json.dumps(t.get("function", t), default=str)
return True
except (TypeError, ValueError, KeyError):
return False Type guard
const isToolDef = (t) => t?.type === 'function' && typeof t.function?.name === 'string'; const allToolsValid = (tools) => !tools || tools.every(isToolDef);
Try / catch
try { ... } catch (e) { if (e.status === 400 && e.detail === 'Invalid tools') { tools = tools.filter(isToolDef); /* resend without the malformed tool */ } } Prevention
- Define tools with a schema validator (zod/pydantic) before every request.
- Never put assistant tool_call messages into the tools field.
- Unit-test your tool builder against json round-tripping.
When it happens
Trigger: POST /v1/chat/completions with tools: [...] where a tool entry is not a proper {type:'function', function:{name, description, parameters}} object; or where function.arguments is a string containing invalid JSON that the model/round-trip previously mangled.
Common situations: Sending back assistant tool_calls payloads as tools; using a client SDK that emits a different tool schema; hand-written tool JSON with missing 'function' wrapper; proxying another provider's tool format verbatim.
Related errors
- Cannot stream function calls.
- Invalid input type {input_item.type}.
- Invalid request
- Cannot stream multiple responses.
- tools is not valid JSON: {tools!r}
AI-assisted analysis of hiyouga/LlamaFactory@f28afaf635 (2026-08-14).
Data as JSON: /api/errors/bf74448c40a5c772.
Report an issue: GitHub.