microsoft/qlib · error · ValueError

invalid memory_mode `{self.memory_mode}`

Error message

invalid memory_mode `{self.memory_mode}`

What it means

The reinforcement-learning dataset in qlib/contrib/data/dataset.py allocates an internal state-memory tensor sized either per sample ('sample') or per trading day ('daily'). memory_mode must be exactly one of these two strings; anything else raises ValueError at dataset construction, after batch slicing is set up.

Source

Thrown at qlib/contrib/data/dataset.py:206

            assert self._data.shape[1] % self.input_size == 0, "data mismatch, please check `input_size`"

        # create batch slices
        self._batch_slices = _create_ts_slices(self._index, self.seq_len)

        # create daily slices
        daily_slices = {date: [] for date in sorted(self._index.unique(level=1))}  # sorted by date
        for i, (code, date) in enumerate(self._index):
            daily_slices[date].append(self._batch_slices[i])
        self._daily_slices = np.array(list(daily_slices.values()), dtype="object")
        self._daily_index = pd.Series(list(daily_slices.keys()))  # index is the original date index

        # add memory (sample wise and daily)
        if self.memory_mode == "sample":
            self._memory = np.zeros((len(self._data), self.num_states), dtype=np.float32)
        elif self.memory_mode == "daily":
            self._memory = np.zeros((len(self._daily_index), self.num_states), dtype=np.float32)
        else:
            raise ValueError(f"invalid memory_mode `{self.memory_mode}`")

        # padding tensor
        self._zeros = np.zeros((self.seq_len, max(self.num_states, self._data.shape[1])), dtype=np.float32)

    def _prepare_seg(self, slc, **kwargs):
        fn = _get_date_parse_fn(self._index[0][1])
        if isinstance(slc, slice):
            start, stop = slc.start, slc.stop
        elif isinstance(slc, (list, tuple)):
            start, stop = slc
        else:
            raise NotImplementedError(f"This type of input is not supported")
        start_date = pd.Timestamp(fn(start))
        end_date = pd.Timestamp(fn(stop))
        obj = copy.copy(self)  # shallow copy
        # NOTE: Seriable will disable copy `self._data` so we manually assign them here
        obj._data = self._data  # reference (no copy)
        obj._label = self._label

View on GitHub (pinned to 79633dd950)

Solutions

  1. Set memory_mode='sample' or memory_mode='daily' explicitly.
  2. If you truly need no state memory, configure the dataset with num_states=0 — then no memory block is allocated and the mode is irrelevant.
  3. Validate the value at config-load time and fail with a clear message listing the allowed values.

Example fix

# before
ds = RLDataSet(data, seq_len=20, num_states=4, memory_mode=None)  # -> ValueError
# after
ds = RLDataSet(data, seq_len=20, num_states=4, memory_mode='sample')  # or 'daily'
Defensive patterns

Strategy: validation

Validate before calling

SUPPORTED_MEM = ('sample', 'daily')
assert memory_mode in SUPPORTED_MEM, f'memory_mode must be one of {SUPPORTED_MEM}, got {memory_mode!r}'

Type guard

def is_valid_memory_mode(m) -> bool:
    return m in ('sample', 'daily')

Prevention

When it happens

Trigger: Constructing the RL dataset (e.g. MTSDataset/DataLoaderRL-family classes) with memory_mode unset (None) or misspelled ('samples', 'per_day', 'Sample'), or with num_states>0 but an invalid memory_mode string.

Common situations: Copy-pasted RL workflow YAML with a renamed field; refactoring that passes None as a placeholder; users assuming memory_mode is optional when num_states>0.

Related errors


AI-assisted analysis of microsoft/qlib@79633dd950 (2026-08-15). Data as JSON: /api/errors/5e405048a41509d0. Report an issue: GitHub.