oobabooga/textgen · error · InvalidRequestError
Invalid tool specification at index {idx}.
Error message
Invalid tool specification at index {idx}. What it means
Each entry in the 'tools' array is parsed into a pydantic ToolDefinition. If parsing raises pydantic ValidationError (wrong shape, missing required 'function.name', non-dict entries, bad parameter schema types), the server raises InvalidRequestError (400, param='tools') with the failing index, then backfills defaults (description, parameters) only for tools that passed validation.
Source
Thrown at modules/api/completions.py:1128
def validateTools(tools: list[dict]):
# Validate each tool definition in the JSON array
valid_tools = None
for idx in range(len(tools)):
tool = tools[idx]
try:
tool_definition = ToolDefinition(**tool)
# Backfill defaults so Jinja2 templates don't crash on missing fields
func = tool.get("function", {})
if "description" not in func:
func["description"] = ""
if "parameters" not in func:
func["parameters"] = {"type": "object", "properties": {}}
if valid_tools is None:
valid_tools = []
valid_tools.append(tool)
except ValidationError:
raise InvalidRequestError(message=f"Invalid tool specification at index {idx}.", param='tools')
return valid_tools
View on GitHub (pinned to ed888c71f2)
Solutions
- Use the canonical shape: {"type": "function", "function": {"name": str, "description": str (optional), "parameters": <JSON schema dict>}}.
- Ensure 'name' is present and a string; it is the only strictly required function field.
- Convert framework tool objects to plain dicts before sending (e.g. LangChain's tool.args schema inside the function key).
- Check the reported index in the message to find the exact broken tool entry.
Example fix
# before
tools = [{"function": {"description": "Get weather", "parameters": {"type": "object", "properties": {"city": {"type": "string"}}}}}]
# 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
def validate_tools(tools):
for i, t in enumerate(tools):
assert isinstance(t, dict), f'tool {i} not a dict'
fn = t.get('function')
assert isinstance(fn, dict) and isinstance(fn.get('name'), str) and fn['name'], f'tool {i} missing function.name'
if 'parameters' in fn:
assert isinstance(fn['parameters'], dict), f'tool {i} parameters must be a JSON schema object'
return tools Type guard
def is_valid_tool(t) -> bool:
return (isinstance(t, dict) and isinstance(t.get('function'), dict)
and isinstance(t['function'].get('name'), str) and len(t['function']['name']) > 0) Try / catch
try:
resp = client.chat.completions.create(model=m, messages=msgs, tools=tools)
except openai.BadRequestError as e:
if 'Invalid tool specification' in str(e):
idx = int(e.message.split('index ')[1].rstrip('.'))
raise ValueError(f'tool[{idx}] malformed: {tools[idx]!r}')
raise Prevention
- Always emit {'type':'function','function':{'name': ...}} with a non-empty string name.
- Convert framework tool objects to plain dicts before sending.
- Validate the tools array client-side with a type guard before the request.
When it happens
Trigger: POST /v1/chat/completions with tools=["get_weather"] (bare string), tools=[{"function": {"parameters": {...}}}] (missing name), tools=[{"type": "function", "function": {"name": 42}}], or a JSON-schema 'parameters' value pydantic cannot coerce.
Common situations: Hand-written tool dicts missing the name field; passing raw Python functions or LangChain tool objects without .dict()/conversion; schema typos like 'paramters'; nested 'parameters' given as a string instead of an object.
Related errors
- functions is not supported.
- function_call is not supported.
- messages is required
- messages: missing role
- role: function is not supported.
AI-assisted analysis of oobabooga/textgen@ed888c71f2 (2026-08-15).
Data as JSON: /api/errors/3a255bc91e130436.
Report an issue: GitHub.