run-llama/llama_index · error · ValueError
Failed to select query engine
Error message
Failed to select query engine
What it means
In RouterQueryEngine._query (sync), after the selector picks a query engine it indexes self._query_engines[result.ind]. If that lookup raises ValueError (index out of range because the LLM selector returned an invalid index), it is re-raised as 'Failed to select query engine' with the original as cause.
Source
Thrown at llama-index-core/llama_index/core/query_engine/router_query_engine.py:193
selected_query_engine = self._query_engines[engine_ind]
responses.append(selected_query_engine.query(query_bundle))
if len(responses) > 1:
final_response = combine_responses(
self._summarizer, responses, query_bundle
)
else:
final_response = responses[0]
else:
try:
selected_query_engine = self._query_engines[result.ind]
log_str = f"Selecting query engine {result.ind}: {result.reason}."
logger.info(log_str)
if self._verbose:
print_text(log_str + "\n", color="pink")
except ValueError as e:
raise ValueError("Failed to select query engine") from e
final_response = selected_query_engine.query(query_bundle)
# add selected result
final_response.metadata = final_response.metadata or {}
final_response.metadata["selector_result"] = result
query_event.on_end(payload={EventPayload.RESPONSE: final_response})
return final_response
async def _aquery(self, query_bundle: QueryBundle) -> RESPONSE_TYPE:
with self.callback_manager.event(
CBEventType.QUERY, payload={EventPayload.QUERY_STR: query_bundle.query_str}
) as query_event:
result = await self._selector.aselect(self._metadatas, query_bundle)
if len(result.inds) > 1:View on GitHub (pinned to afd0fef371)
Solutions
- Use a stronger instruction-following LLM for routing (e.g. an OpenAI function-calling model with PydanticSingleSelector)
- Pass an explicit selector: RouterQueryEngine(..., selector=get_selector_from_llm(llm)) with a reliable LLM, rather than relying on the default
- Verify the QueryEngineTool list is small and well-differentiated so the selector's numbered choice is unambiguous
- Catch ValueError and retry the query or fall back to a default engine
Example fix
// before
router = RouterQueryEngine(selector=LLMSingleSelector.from_defaults(llm=weak_llm), query_engine_tools=tools)
resp = router.query(q)
// after
from llama_index.core.selectors import PydanticSingleSelector
router = RouterQueryEngine(
selector=PydanticSingleSelector.from_defaults(llm=strong_llm),
query_engine_tools=tools,
)
resp = router.query(q) Defensive patterns
Strategy: retry
Validate before calling
# Validate selector sanity before querying: choices must match engines assert router_engine._selector is not None # keep engine/tool counts aligned at construction time: # RouterQueryEngine(query_engine_tools=tools) builds both from the same list, prefer that API
Try / catch
try:
resp = router_engine.query(q)
except ValueError as e:
if "Failed to select query engine" in str(e) and e.__cause__ is not None:
resp = router_engine.query(q) # one retry; selector output is nondeterministic
else:
raise Prevention
- Route with function-calling LLMs (PydanticSingleSelector) rather than text-parsing selectors
- Prefer RouterQueryEngine.from_defaults(query_engine_tools=tools) so selector choices and engines stay aligned
- Log selector results to spot invalid indices early
When it happens
Trigger: Single-selection routing where the selector LLM returns result.ind outside 0..len(query_engines)-1 (e.g. returns 2 when only 2 engines exist, or a tool index misaligned with the choices list).
Common situations: Weak or non-instruct LLM that fails to follow the selector output format; a custom selector whose choices list order does not match the query_engines list; flaky structured-output parsing in the Pydantic/LLM selector.
Related errors
- There are {len(self.reasons)} selections, please use .reason
- Invalid result.ind: {result.ind}
- Failed to select retriever
- Unknown tool name: {tool_call_result.tool_name}
- There are {len(self.selections)} selections, please use .ind
AI-assisted analysis of run-llama/llama_index@afd0fef371 (2026-08-15).
Data as JSON: /api/errors/8dd20be487770c4d.
Report an issue: GitHub.