run-llama/llama_index · error · ValueError
Failed to select retriever
Error message
Failed to select retriever
What it means
RouterRetriever._retrieve asks a selector to pick one of its candidate retrievers and then indexes self._retrievers with result.ind. If the selector returns an index that cannot resolve to a retriever, the failed lookup is re-raised as ValueError('Failed to select retriever'). In practice the selector (often an LLM-backed one) produced an index that does not map to the registered retriever_tools list.
Source
Thrown at llama-index-core/llama_index/core/retrievers/router_retriever.py:99
payload={EventPayload.QUERY_STR: query_bundle.query_str},
) as query_event:
result = self._selector.select(self._metadatas, query_bundle)
if len(result.inds) > 1:
retrieved_results = {}
for i, engine_ind in enumerate(result.inds):
logger.info(
f"Selecting retriever {engine_ind}: {result.reasons[i]}."
)
selected_retriever = self._retrievers[engine_ind]
cur_results = selected_retriever.retrieve(query_bundle)
retrieved_results.update({n.node.node_id: n for n in cur_results})
else:
try:
selected_retriever = self._retrievers[result.ind]
logger.info(f"Selecting retriever {result.ind}: {result.reason}.")
except ValueError as e:
raise ValueError("Failed to select retriever") from e
cur_results = selected_retriever.retrieve(query_bundle)
retrieved_results = {n.node.node_id: n for n in cur_results}
query_event.on_end(payload={EventPayload.NODES: retrieved_results.values()})
return list(retrieved_results.values())
async def _aretrieve(self, query_bundle: QueryBundle) -> List[NodeWithScore]:
with self.callback_manager.event(
CBEventType.RETRIEVE,
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:
retrieved_results = {}
tasks = []View on GitHub (pinned to afd0fef371)
Solutions
- Switch to a Pydantic/structured selector (RouterRetriever.from_defaults with an LLMPydanticSingleSelector) so the LLM cannot emit an out-of-range index
- Verify len(retriever_tools) matches the numbered choices the selector sees, and that your custom BaseSelector returns 0-based indexes within range
- Use a stronger LLM for selection (the default prompt asks the model to pick by number; small models frequently miscount)
- Reduce the number of choices, or set select_multi=False so only one index must be parsed
Example fix
# before
router = RouterRetriever.from_defaults(retriever_tools=tools, select_multi=False)
# after
from llama_index.core.selectors import LLMSingleSelector
from llama_index.core.selectors.pydantic_selectors import PydanticSingleSelector
router = RouterRetriever.from_defaults(
retriever_tools=tools,
selector=PydanticSingleSelector.from_defaults(), # structured output, index always in range
) Defensive patterns
Strategy: try-catch
Validate before calling
n = len(retriever_tools) assert all(0 <= i < n for i in range(n)), "tool count sanity" # and for custom selectors: # assert 0 <= selector_result.ind < len(retriever_tools)
Type guard
def valid_selection(ind: int, n_tools: int) -> bool:
return isinstance(ind, int) and 0 <= ind < n_tools Try / catch
try:
nodes = router_retriever.retrieve(query)
except ValueError as e:
if "Failed to select retriever" in str(e):
nodes = fallback_retriever.retrieve(query) # log selector failure first
else:
raise Prevention
- Prefer pydantic/structured selectors over free-text LLM selectors
- Keep retriever_tools count small and stable
- Test custom selectors return 0-based in-range indexes
When it happens
Trigger: Calling retrieve() on a RouterRetriever (or RouterQueryEngine) where the selector's chosen result.ind fails to index into the retriever list — e.g. an LLMSingleSelector parses the model's answer into an index that is out of range for the number of RetrieverTools supplied.
Common situations: Using LLMSingleSelector/LLMMultiSelector with a weak LLM that emits a wrong number in the selection output; adding/removing retriever_tools so indexes no longer match the prompt's numbered choices; custom selectors returning 1-based indexes.
Related errors
- There are {len(self.reasons)} selections, please use .reason
- Failed to select query engine
- Retrieved more than one node.
- LLM must be a FunctionCallingLLM
- At least one agent must be provided
AI-assisted analysis of run-llama/llama_index@afd0fef371 (2026-08-15).
Data as JSON: /api/errors/a17cd74e39e4769d.
Report an issue: GitHub.