{"record":{"id":"77894865c5ee4de0","repo":"run-llama/llama_index","slug":"there-are-len-self-reasons-selections-please-u","errorCode":null,"errorMessage":"There are {len(self.reasons)} selections, please use .reasons.","messagePattern":"There are (.+?) selections, please use \\.reasons\\.","errorType":"exception","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"llama-index-core/llama_index/core/base/base_selector.py","lineNumber":36,"sourceCode":"\n\nclass MultiSelection(BaseModel):\n    \"\"\"A multi-selection of choices.\"\"\"\n\n    selections: List[SingleSelection]\n\n    @property\n    def ind(self) -> int:\n        if len(self.selections) != 1:\n            raise ValueError(\n                f\"There are {len(self.selections)} selections, please use .inds.\"\n            )\n        return self.selections[0].index\n\n    @property\n    def reason(self) -> str:\n        if len(self.reasons) != 1:\n            raise ValueError(\n                f\"There are {len(self.reasons)} selections, please use .reasons.\"\n            )\n        return self.selections[0].reason\n\n    @property\n    def inds(self) -> List[int]:\n        return [x.index for x in self.selections]\n\n    @property\n    def reasons(self) -> List[str]:\n        return [x.reason for x in self.selections]\n\n\n# separate name for clarity and to not confuse function calling model\nSelectorResult = MultiSelection\n\n\ndef _wrap_choice(choice: MetadataType) -> ToolMetadata:","sourceCodeStart":18,"sourceCodeEnd":54,"githubUrl":"https://github.com/run-llama/llama_index/blob/afd0fef371831f9bda13e5af7167cf4e981278ab/llama-index-core/llama_index/core/base/base_selector.py#L18-L54","documentation":"Raised by SelectorResult.reason when a multi-selection selector result holds more than (or fewer than) exactly one selection. The single-value accessor .reason only works when len(self.selections) == 1; for multi-choice routing you must read the list property .reasons instead. Note the message says '.reasons' while the sibling property .ind tells you to use .inds' plural accessors.","triggerScenarios":"Calling selector_result.reason after a selector (e.g. PydanticSingleSelector vs PydanticMultiSelector) ran with multiple choices, or when the LLM returned multiple JSON selections. Any .select() call over >1 choices using a multi-selector returns a MultiSelection where len(selections) != 1.","commonSituations":"Switching a router/query engine from a single-selector to a multi-selector (e.g. RouterQueryEngine with selector_type=PydanticMultiSelector) but still reading .reason/.ind; LLM emitting several selections for a single-choice prompt.","solutions":["If you expect multiple selections, read selector_result.reasons (list of str) and selector_result.inds (list of int) instead of .reason/.ind.","If you expect exactly one selection, switch the selector to a single selector (e.g. PydanticSingleSelector or LLMSingleSelector) so only one selection is produced.","Inspect len(selector_result.selections) before choosing the accessor and branch accordingly."],"exampleFix":"// before\nsel = await selector.select(choices, query)\nreason = sel.reason  # ValueError if multiple selections\n\n// after\nsel = await selector.select(choices, query)\nif len(sel.selections) == 1:\n    reason = sel.reason\nelse:\n    reasons = sel.reasons  # List[str]","handlingStrategy":"type-guard","validationCode":"result = selector.select(choices, query)\nif len(result.selections) != 1:\n    reasons = result.reasons\n    inds = result.inds\nelse:\n    reason, ind = result.reason, result.ind","typeGuard":"def is_single_selection(r: SelectorResult) -> bool:\n    return len(r.selections) == 1","tryCatchPattern":"try:\n    reason = result.reason\nexcept ValueError:\n    reason = result.reasons  # fall back to list accessor","preventionTips":["Always branch on len(result.selections) before using singular accessors.","Match your selector class (single vs multi) to how you read results."],"tags":["llama-index","selector","router","multi-select"],"backgroundTag":null,"analyzedSha":"afd0fef371831f9bda13e5af7167cf4e981278ab","analyzedAt":"2026-08-15T05:42:58.429Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}