{"record":{"id":"d627edee3895eddd","repo":"microsoft/qlib","slug":"subclass-of-featurestorage-must-implement-data-m","errorCode":null,"errorMessage":"Subclass of FeatureStorage must implement `data` method","messagePattern":"Subclass of FeatureStorage must implement `data` method","errorType":"exception","errorClass":"NotImplementedError","httpStatus":null,"severity":"error","filePath":"qlib/data/storage/storage.py","lineNumber":270,"sourceCode":"        raise NotImplementedError(\"Subclass of InstrumentStorage must implement `__len__`  method\")\n\n\nclass FeatureStorage(BaseStorage):\n    def __init__(self, instrument: str, field: str, freq: str, **kwargs):\n        self.instrument = instrument\n        self.field = field\n        self.freq = freq\n        self.kwargs = kwargs\n\n    @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)","sourceCodeStart":252,"sourceCodeEnd":288,"githubUrl":"https://github.com/microsoft/qlib/blob/79633dd9506ea689e5400dea0197717b5b3d74b7/qlib/data/storage/storage.py#L252-L288","documentation":"qlib's FeatureStorage is an abstract base class (qlib/data/storage/storage.py:270) representing storage for a single feature column (e.g. one instrument's price series). The `data` property is deliberately unimplemented: every concrete storage backend (FileFeatureStorage, ULTRA frequent storage, etc.) must override it to return the full data as a pd.Series. Accessing `.data` on the raw base class, or on a subclass that failed to override it, raises NotImplementedError.","triggerScenarios":"Instantiating qlib.data.storage.storage.FeatureStorage (or a custom subclass) directly and reading the `data` property; writing a custom FeatureStorage backend and forgetting to implement the `data` property; a storage factory returning the base class instead of a concrete implementation.","commonSituations":"Implementing a custom storage backend for a new file format or database; accidentally subclassing the wrong class (e.g. the base FeatureStorage instead of FeatureStorage subclass used by the storage factory); a partially-written backend class during development.","solutions":["Use a concrete implementation such as qlib.data.storage.file_storage.FileFeatureStorage instead of the base class","If subclassing FeatureStorage yourself, implement the `data` property returning a pd.Series (return pd.Series(dtype=np.float32) when storage does not exist)","Check via qlib.data.storage.storage.get_storage_type / the storage factory that you are receiving a concrete storage instance","Verify no monkey-patching or import shadowing replaces the concrete storage class with the base class"],"exampleFix":"// before\nstorage = FeatureStorage(instrument, field, freq)\nseries = storage.data  # NotImplementedError\n\n// after\nfrom qlib.data.storage.file_storage import FileFeatureStorage\nstorage = FileFeatureStorage(instrument, field, freq)\nseries = storage.data  # pd.Series","handlingStrategy":"type-guard","validationCode":"from qlib.data.storage.storage import FeatureStorage\nassert not type(storage) is FeatureStorage, 'abstract FeatureStorage cannot be used directly'\nassert type(storage).data is not FeatureStorage.data, 'subclass must override `data`'","typeGuard":"def has_concrete_data(storage) -> bool:\n    return hasattr(storage, 'data') and type(storage).data is not FeatureStorage.data","tryCatchPattern":"try:\n    series = storage.data\nexcept NotImplementedError as e:\n    raise TypeError(f'{type(storage).__name__} is not a concrete FeatureStorage backend') from e","preventionTips":["Always obtain storage instances via qlib's storage factory rather than direct instantiation","Write a checklist test that asserts every custom backend overrides data/start_index/end_index/clear/write"],"tags":["qlib","storage","abstract-method","not-implemented","data"],"backgroundTag":null,"analyzedSha":"79633dd9506ea689e5400dea0197717b5b3d74b7","analyzedAt":"2026-08-15T07:01:27.511Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}