{"record":{"id":"d1d1ac2a00884bd7","repo":"microsoft/qlib","slug":"i-forget-why-would-this-case-appear-but-i-think-i","errorCode":null,"errorMessage":"I forget why would this case appear. But I think it does not make sense. So we raise a error for that case.","messagePattern":"I forget why would this case appear\\. But I think it does not make sense\\. So we raise a error for that case\\.","errorType":"exception","errorClass":"TypeError","httpStatus":null,"severity":"error","filePath":"qlib/data/dataset/storage.py","lineNumber":147,"sourceCode":"        \"\"\"\n\n        stock_selector = slice(None)\n        time_selector = slice(None)  # by default not filter by time.\n\n        if level is None:\n            # For directly applying.\n            if isinstance(selector, tuple) and self.stock_level < len(selector):\n                # full selector format\n                stock_selector = selector[self.stock_level]\n                time_selector = selector[1 - self.stock_level]\n            elif isinstance(selector, (list, str)) and self.stock_level == 0:\n                # only stock selector\n                stock_selector = selector\n        elif level in (\"instrument\", self.stock_level):\n            if isinstance(selector, tuple):\n                # NOTE: How could the stock level selector be a tuple?\n                stock_selector = selector[0]\n                raise TypeError(\n                    \"I forget why would this case appear. But I think it does not make sense. So we raise a error for that case.\"\n                )\n            elif isinstance(selector, (list, str)):\n                stock_selector = selector\n\n        if not isinstance(stock_selector, (list, str)) and stock_selector != slice(None):\n            raise TypeError(f\"stock selector must be type str|list, or slice(None), rather than {stock_selector}\")\n\n        if stock_selector == slice(None):\n            return self.hash_df, time_selector\n\n        if isinstance(stock_selector, str):\n            stock_selector = [stock_selector]\n\n        select_dict = dict()\n        for each_stock in sorted(stock_selector):\n            if each_stock in self.hash_df:\n                select_dict[each_stock] = self.hash_df[each_stock]","sourceCodeStart":129,"sourceCodeEnd":165,"githubUrl":"https://github.com/microsoft/qlib/blob/79633dd9506ea689e5400dea0197717b5b3d74b7/qlib/data/dataset/storage.py#L129-L165","documentation":"A defensive TypeError in UCData/storage selector parsing (qlib/data/dataset/storage.py). When selecting at the instrument level, a selector of type tuple is considered nonsensical: the code assigns stock_selector = selector[0] and then immediately raises, with an apologetic message ('I forget why would this case appear...'). In practice this branch is unreachable defensive code guarding against unexpected selector shapes reaching the instrument level.","triggerScenarios":"Calling the storage's selector-normalization path with level in (\"instrument\", stock_level) and a tuple selector, e.g. data[('SH600000', slice(None))] where the API expects level=\"instrument\" to receive a plain list/str. Only reachable through internal APIs that pass raw user selectors down to this method.","commonSituations":"Passing a (stock, time) tuple selector to a method that only expects an instrument selector at that level; misuse of low-level storage APIs instead of the public Series/DataFrame interfaces. End users of qlib's public APIs rarely hit this; it mainly guards internal invariants.","solutions":["Pass the instrument selector directly (a string or list of instrument codes), not a tuple: use \"SH600000\" or [\"SH600000\"] instead of (\"SH600000\", ...).","If you need both stock and time selection, call the API that accepts a full tuple selector with level=\"multi_index\" or per the storage's documented selector format.","If you genuinely believe a tuple is valid here, report upstream — the source comment itself says the authors were unsure this case can occur."],"exampleFix":"// before (conceptual)\nstorage.get_selector(selector=(\"SH600000\", slice(None)), level=\"instrument\")\n\n// after\nstorage.get_selector(selector=\"SH600000\", level=\"instrument\")","handlingStrategy":"type-guard","validationCode":"assert not isinstance(selector, tuple), \"instrument-level selector must not be a tuple; pass str or list\"","typeGuard":"def is_instrument_selector(s) -> bool:\n    return isinstance(s, (str, list)) or s == slice(None)","tryCatchPattern":null,"preventionTips":["Pass only str/list at instrument level; reserve tuple selectors for multi-level APIs.","Wrap storage access behind your own helper that normalizes selectors once."],"tags":["qlib","storage","selector","internal-api"],"backgroundTag":null,"analyzedSha":"79633dd9506ea689e5400dea0197717b5b3d74b7","analyzedAt":"2026-08-15T07:01:27.511Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}