microsoft/qlib · error · NotImplementedError
Subclass of FeatureStorage must implement `end_index` method
Error message
Subclass of FeatureStorage must implement `end_index` method
What it means
FeatureStorage.end_index (qlib/data/storage/storage.py:294) is abstract: it must return the right (closed) boundary of the data range, where the next append point is end_index + 1, or None when storage does not exist. The base class raises NotImplementedError because each backend stores range metadata differently (e.g. in a .start/end file, in a binary header, or computed from the data).
Source
Thrown at qlib/data/storage/storage.py:294
Notes
-----
If the data(storage) does not exist, return None
"""
raise NotImplementedError("Subclass of FeatureStorage must implement `start_index` method")
@property
def end_index(self) -> Union[int, None]:
"""get FeatureStorage end index
Notes
-----
The right index of the data range (both sides are closed)
The next data appending point will be `end_index + 1`
If the data(storage) does not exist, return None
"""
raise NotImplementedError("Subclass of FeatureStorage must implement `end_index` method")
def clear(self) -> None:
raise NotImplementedError("Subclass of FeatureStorage must implement `clear` method")
def write(self, data_array: Union[List, np.ndarray, Tuple], index: int = None):
"""Write data_array to FeatureStorage starting from index.
Notes
------
If index is None, append data_array to feature.
If len(data_array) == 0; return
If (index - self.end_index) >= 1, self[end_index+1: index] will be filled with np.nan
Examples
---------
.. code-block::View on GitHub (pinned to 79633dd950)
Solutions
- Use an existing concrete implementation (FileFeatureStorage) via the storage factory
- Implement `end_index` in your subclass returning the last stored index or None if empty
- Implement the full abstract interface (data, start_index, end_index, clear, write) before using the subclass
- Add unit tests that instantiate your backend and assert start/end index behavior
Example fix
// before
class MyStorage(FeatureStorage):
...
# no end_index -> NotImplementedError on append
// after
class MyStorage(FeatureStorage):
@property
def end_index(self):
return None if len(self.data) == 0 else int(self.data.index[-1]) Defensive patterns
Strategy: type-guard
Validate before calling
from qlib.data.storage.storage import FeatureStorage assert type(storage).end_index is not FeatureStorage.end_index, 'end_index not implemented'
Type guard
def has_concrete_end_index(storage) -> bool:
return type(storage).end_index is not FeatureStorage.end_index Try / catch
try:
ei = storage.end_index
except NotImplementedError as e:
raise TypeError(f'{type(storage).__name__} lacks end_index implementation') from e Prevention
- Cover all five abstract members when implementing a backend; use a test that touches each one
- Log the concrete storage class returned by factories in debug builds
When it happens
Trigger: Reading `.end_index` on FeatureStorage directly or on a subclass missing this property; append logic (write with index=None) that first consults end_index to find the append position; rebase() which reads both start_index and end_index.
Common situations: Writing a custom backend and forgetting the range properties; extending qlib's storage layer for a new data format; running dataset dump scripts that query storage boundaries.
Related errors
- Subclass of FeatureStorage must implement `start_index` meth
- Subclass of FeatureStorage must implement `data` method
- Subclass of FeatureStorage must implement `clear` method
- Subclass of FeatureStorage must implement `write` method
- Please implement the `get_all_stock` method
AI-assisted analysis of microsoft/qlib@79633dd950 (2026-08-15).
Data as JSON: /api/errors/a9d072de954cf0e6.
Report an issue: GitHub.