microsoft/qlib · error · TypeError

Only processors usable for inference can be used in `infer_p

Error message

Only processors usable for inference can be used in `infer_processors` 

What it means

DataHandlerLP runs `infer_processors` on data that is also served at inference time. Processors declare themselves inference-safe via `is_for_infer()`; those that leak future information (e.g. processors derived for labels, `is_for_infer() == False`) are forbidden in that list and raise TypeError with a trailing space in the message.

Source

Thrown at qlib/data/dataset/handler.py:535

        for proc in self.get_all_processors():
            with TimeInspector.logt(f"{proc.__class__.__name__}"):
                proc.fit(self._data)

    def fit_process_data(self):
        """
        fit and process data

        The input of the `fit` will be the output of the previous processor
        """
        self.process_data(with_fit=True)

    @staticmethod
    def _run_proc_l(
        df: pd.DataFrame, proc_l: List[processor_module.Processor], with_fit: bool, check_for_infer: bool
    ) -> pd.DataFrame:
        for proc in proc_l:
            if check_for_infer and not proc.is_for_infer():
                raise TypeError("Only processors usable for inference can be used in `infer_processors` ")
            with TimeInspector.logt(f"{proc.__class__.__name__}"):
                if with_fit:
                    proc.fit(df)
                df = proc(df)
        return df

    @staticmethod
    def _is_proc_readonly(proc_l: List[processor_module.Processor]):
        """
        NOTE: it will return True if `len(proc_l) == 0`
        """
        for p in proc_l:
            if not p.readonly():
                return False
        return True

    def process_data(self, with_fit: bool = False):
        """

View on GitHub (pinned to 79633dd950)

Solutions

  1. Move the offending processor to `learn_processors`.
  2. If the processor is genuinely inference-safe, override `is_for_infer()` in its class to return True after verifying it uses no future data.

Example fix

# before (config)
data_handler_config = {
    'infer_processors': ['CorrProcessor'],   # learn-only
    'learn_processors': ['RobustZScoreNorm'],
}

# after
data_handler_config = {
    'infer_processors': ['RobustZScoreNorm'],
    'learn_processors': ['CorrProcessor'],
}
Defensive patterns

Strategy: validation

Validate before calling

def all_infer_safe(proc_l) -> bool:
    return all(p.is_for_infer() for p in proc_l)

# before DataHandlerLP setup
assert all_infer_safe(handler_config['infer_processors']), 'infer_processors contain learn-only processors'

Type guard

def is_infer_safe(proc) -> bool:
    return bool(proc.is_for_infer())

Prevention

When it happens

Trigger: Configuring DataHandlerLP with `infer_processors=[SomeLearnOnlyProcessor()]` where the processor's class sets `is_for_infer = False` (or is_for_infer() returns False) — commonly label-related or fit-on-full-data processors.

Common situations: Copy-pasting a processor list from `learn_processors` into `infer_processors` in workflow configs; processors that normalize using statistics of the full period.

Related errors


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