{"record":{"id":"2b54196045445a4b","repo":"microsoft/qlib","slug":"subclass-of-featurestorage-must-implement-start-i","errorCode":null,"errorMessage":"Subclass of FeatureStorage must implement `start_index` method","messagePattern":"Subclass of FeatureStorage must implement `start_index` method","errorType":"exception","errorClass":"NotImplementedError","httpStatus":null,"severity":"error","filePath":"qlib/data/storage/storage.py","lineNumber":280,"sourceCode":"    @property\n    def data(self) -> pd.Series:\n        \"\"\"get all data\n\n        Notes\n        ------\n        if data(storage) does not exist, return empty pd.Series: `return pd.Series(dtype=np.float32)`\n        \"\"\"\n        raise NotImplementedError(\"Subclass of FeatureStorage must implement `data` method\")\n\n    @property\n    def start_index(self) -> Union[int, None]:\n        \"\"\"get FeatureStorage start index\n\n        Notes\n        -----\n        If the data(storage) does not exist, return None\n        \"\"\"\n        raise NotImplementedError(\"Subclass of FeatureStorage must implement `start_index` method\")\n\n    @property\n    def end_index(self) -> Union[int, None]:\n        \"\"\"get FeatureStorage end index\n\n        Notes\n        -----\n        The  right index of the data range (both sides are closed)\n\n            The next  data appending point will be  `end_index + 1`\n\n        If the data(storage) does not exist, return None\n        \"\"\"\n        raise NotImplementedError(\"Subclass of FeatureStorage must implement `end_index` method\")\n\n    def clear(self) -> None:\n        raise NotImplementedError(\"Subclass of FeatureStorage must implement `clear` method\")\n","sourceCodeStart":262,"sourceCodeEnd":298,"githubUrl":"https://github.com/microsoft/qlib/blob/79633dd9506ea689e5400dea0197717b5b3d74b7/qlib/data/storage/storage.py#L262-L298","documentation":"FeatureStorage.start_index (qlib/data/storage/storage.py:280) is an abstract property meant to return the left (inclusive) index of the stored data range, or None if the storage is empty. The base class raises NotImplementedError to force concrete backends (FileFeatureStorage, etc.) to define how the first data index is located. Reading `.start_index` on the base class or an incomplete subclass triggers this error.","triggerScenarios":"Accessing `.start_index` on a directly instantiated FeatureStorage; implementing a custom storage backend without overriding the `start_index` property; code paths (e.g. rebase, calendar alignment) that query the range of a storage object that is actually the abstract base.","commonSituations":"Developing a custom storage backend and only implementing `data`/`write`; refactoring storage code so a factory accidentally returns the base class; testing with a mock that does not subclass correctly.","solutions":["Use a concrete backend like FileFeatureStorage rather than the abstract base","Implement `start_index` in your subclass: return the first index of the stored data, or None if storage does not exist","Ensure any custom storage registered via the storage factory fully implements the FeatureStorage interface (data, start_index, end_index, clear, write)","Audit isinstance checks so abstract instances are rejected before use"],"exampleFix":"// before\nclass MyStorage(FeatureStorage):\n    @property\n    def data(self):\n        return pd.Series(...)\n# start_index not overridden -> NotImplementedError\n\n// after\nclass MyStorage(FeatureStorage):\n    @property\n    def data(self):\n        return pd.Series(...)\n\n    @property\n    def start_index(self):\n        return None if len(self.data) == 0 else int(self.data.index[0])","handlingStrategy":"type-guard","validationCode":"from qlib.data.storage.storage import FeatureStorage\nassert type(storage).start_index is not FeatureStorage.start_index, 'start_index not implemented'","typeGuard":"def has_concrete_start_index(storage) -> bool:\n    return type(storage).start_index is not FeatureStorage.start_index","tryCatchPattern":"try:\n    si = storage.start_index\nexcept NotImplementedError as e:\n    raise TypeError(f'{type(storage).__name__} lacks start_index implementation') from e","preventionTips":["Treat FeatureStorage as an interface; never instantiate the base class","Add abstract-interface conformance tests for custom storage backends"],"tags":["qlib","storage","abstract-method","not-implemented","index"],"backgroundTag":null,"analyzedSha":"79633dd9506ea689e5400dea0197717b5b3d74b7","analyzedAt":"2026-08-15T07:01:27.511Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}