{"record":{"id":"70486e965c8011c9","repo":"microsoft/qlib","slug":"subclass-of-featurestorage-must-implement-write","errorCode":null,"errorMessage":"Subclass of FeatureStorage must implement `write` method","messagePattern":"Subclass of FeatureStorage must implement `write` method","errorType":"exception","errorClass":"NotImplementedError","httpStatus":null,"severity":"error","filePath":"qlib/data/storage/storage.py","lineNumber":352,"sourceCode":"                    5   6\n                    6   6\n                    7   7\n                    8   np.nan\n                    9   8\n\n            >>> self.write([1, np.nan], index=3)\n\n                feature:\n                    3   1\n                    4   np.nan\n                    5   6\n                    6   6\n                    7   7\n                    8   np.nan\n                    9   8\n\n        \"\"\"\n        raise NotImplementedError(\"Subclass of FeatureStorage must implement `write` method\")\n\n    def rebase(self, start_index: int = None, end_index: int = None):\n        \"\"\"Rebase the start_index and end_index of the FeatureStorage.\n\n        start_index and end_index are closed intervals: [start_index, end_index]\n\n        Examples\n        ---------\n\n            .. code-block::\n\n                    feature:\n                        3   4\n                        4   5\n                        5   6\n\n\n                >>> self.rebase(start_index=4)","sourceCodeStart":334,"sourceCodeEnd":370,"githubUrl":"https://github.com/microsoft/qlib/blob/79633dd9506ea689e5400dea0197717b5b3d74b7/qlib/data/storage/storage.py#L334-L370","documentation":"FeatureStorage.write (qlib/data/storage/storage.py:352) is the abstract method that persists a data_array starting at a given index (appending when index is None, filling gaps with NaN, ignoring empty arrays). The base class raises NotImplementedError; each backend must define how values are serialized. Calling write() without a concrete subclass implementation triggers this error.","triggerScenarios":"Calling storage.write(data_array, index) or storage.write(data_array) on the base class; custom backend missing the write() override; dump scripts (e.g. dump_bin.py data writing) that use the storage factory but receive the wrong class.","commonSituations":"Implementing a new storage backend and finishing read paths first; subclassing FeatureStorage for tests/stubs; mismatches where a factory or config selects an unregistered storage class.","solutions":["Use FileFeatureStorage (or another concrete backend) from the storage factory for writing","Implement write(data_array, index=None) in your subclass honoring the documented semantics (append, NaN gap fill, skip empty arrays)","Check the storage class returned by get_storage(...) with isinstance/cls name before writing","Register your custom backend properly with the storage factory so the correct class is instantiated"],"exampleFix":"// before\nstorage = FeatureStorage(instrument, field, freq)\nstorage.write(np.arange(10), index=0)  # NotImplementedError\n\n// after\nfrom qlib.data.storage.file_storage import FileFeatureStorage\nstorage = FileFeatureStorage(instrument, field, freq)\nstorage.write(np.arange(10), index=0)","handlingStrategy":"type-guard","validationCode":"from qlib.data.storage.storage import FeatureStorage\nassert type(storage).write is not FeatureStorage.write, 'write not implemented'","typeGuard":"def is_writable_storage(storage) -> bool:\n    return type(storage).write is not FeatureStorage.write","tryCatchPattern":"try:\n    storage.write(arr, index=idx)\nexcept NotImplementedError as e:\n    raise TypeError(f'cannot write via {type(storage).__name__}; use a concrete backend') from e","preventionTips":["Route writes through the storage factory so concrete classes are selected","Unit-test write/append/gap-fill behavior for custom backends before integrating"],"tags":["qlib","storage","abstract-method","not-implemented","write"],"backgroundTag":null,"analyzedSha":"79633dd9506ea689e5400dea0197717b5b3d74b7","analyzedAt":"2026-08-15T07:01:27.511Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}