run-llama/llama_index · error · ValueError
LLM must be a FunctionCallingLLM
Error message
LLM must be a FunctionCallingLLM
What it means
RetrieverTool.call builds a query string by concatenating positional args and stringified kwargs; if both are absent/empty the query string stays empty and the tool raises, because retrieving against an empty query is meaningless. Note the guard fires only when query_str == "" exactly — empty-string args still append newline characters and pass.
Source
Thrown at llama-index-core/llama_index/core/agent/workflow/function_agent.py:110
current_agent_name=self.name,
thinking_delta=last_chat_response.additional_kwargs.get(
"thinking_delta", None
),
)
)
return last_chat_response
async def take_step(
self,
ctx: AgentContext,
llm_input: List[ChatMessage],
tools: Sequence[AsyncBaseTool],
memory: BaseMemory,
) -> AgentOutput:
"""Take a single step with the function calling agent."""
if not self.llm.metadata.is_function_calling_model:
raise ValueError("LLM must be a FunctionCallingLLM")
scratchpad: List[ChatMessage] = await ctx.store.get(
self.scratchpad_key, default=[]
)
current_llm_input = [*llm_input, *scratchpad]
ctx.write_event_to_stream(
AgentInput(input=current_llm_input, current_agent_name=self.name)
)
if self.streaming:
last_chat_response = await self._get_streaming_response(
ctx, current_llm_input, tools
)
else:
last_chat_response = await self._get_response(current_llm_input, tools)
tool_calls = self.llm.get_tool_calls_from_response( # type: ignoreView on GitHub (pinned to afd0fef371)
Solutions
- Always pass the query: tool.call('What is X?') or tool.call(input='What is X?').
- Validate before dispatch: skip or re-prompt when the tool call has no non-empty arguments.
- Tighten the tool's fn_schema so the query argument is required, pushing the LLM to supply it.
- Catch ValueError around tool dispatch and re-ask the model for corrected arguments.
Example fix
# before
out = retriever_tool.call() # ValueError: Cannot call query engine without inputs
# after
query = "What are the key features?"
if not query.strip():
raise ValueError("empty query from upstream")
out = retriever_tool.call(query) Defensive patterns
Strategy: validation
Validate before calling
if not args and not kwargs:
raise ValueError('refusing to call retriever tool with empty input')
result = tool.call(*args, **kwargs) Type guard
def has_tool_input(args: tuple, kwargs: dict) -> bool:
return len(args) > 0 or len(kwargs) > 0 Try / catch
try:
out = tool.call(*args, **kwargs)
except ValueError as e:
if 'without inputs' in str(e):
out = tool.call(input=clarified_query) # re-prompt for the query
else:
raise Prevention
- Always pass a query when invoking RetrieverTool.
- Make the query argument required in fn_schema.
- Check tool-call arguments are non-empty before dispatching in agent loops.
When it happens
Trigger: Calling tool.call() with no arguments; an agent dispatching the tool with an empty arguments object (LLM emitted no tool args); programmatic tool routers that forward empty payloads.
Common situations: LLM tool calls with missing arguments (schema not enforced); custom orchestration calling tools with only empty strings; testing harnesses invoking all tools with no payload; prompt templates that leave the query field blank.
Related errors
- At least one agent must be provided
- Max iterations of {max_iterations} reached! Either something
- No tool calls found, cannot aggregate results.
- Tool {tool.metadata.name} requires context. CodeActAgent onl
- Tool {tool.metadata.name} is not a FunctionTool. CodeActAgen
AI-assisted analysis of run-llama/llama_index@afd0fef371 (2026-08-15).
Data as JSON: /api/errors/85cc0f58bf9844e8.
Report an issue: GitHub.