microsoft/qlib · error · NotImplementedError

Please implement the `_get_recorder` method

Error message

Please implement the `_get_recorder` method

What it means

_get_recorder is the protected lookup primitive of qlib's Experiment base class: given a recorder_id/recorder_name it must return the matching Recorder or raise ValueError. The base implementation is a stub, so this NotImplementedError means no concrete lookup backend (e.g. MLflowExperiment._get_recorder, which calls MlflowClient.get_run) is in place.

Source

Thrown at qlib/workflow/exp.py:216

        Get specific recorder by name or id. If it does not exist, raise ValueError

        Parameters
        ----------
        recorder_id :
            The id of recorder
        recorder_name :
            The name of recorder

        Returns
        -------
        Recorder:
            The searched recorder

        Raises
        ------
        ValueError
        """
        raise NotImplementedError(f"Please implement the `_get_recorder` method")

    RT_D = "dict"  # return type dict
    RT_L = "list"  # return type list

    def list_recorders(
        self, rtype: Literal["dict", "list"] = RT_D, **flt_kwargs
    ) -> Union[List[Recorder], Dict[str, Recorder]]:
        """
        List all the existing recorders of this experiment. Please first get the experiment instance before calling this method.
        If user want to use the method `R.list_recorders()`, please refer to the related API document in `QlibRecorder`.

        flt_kwargs : dict
            filter recorders by conditions
            e.g.  list_recorders(status=Recorder.STATUS_FI)

        Returns
        -------
        The return type depends on `rtype`

View on GitHub (pinned to 79633dd950)

Solutions

  1. Use MLflowExperiment (via qlib.init defaults) whose _get_recorder resolves runs through MLflow.
  2. In a custom subclass, implement _get_recorder(self, recorder_id=None, recorder_name=None) returning your Recorder or raising ValueError when not found.
  3. Prefer the public get_recorder API and ensure your subclass fully implements the private hooks it relies on.

Example fix

# before
class MyExp(Experiment):
    ...
exp.get_recorder(recorder_id='abc')  # base _get_recorder -> NotImplementedError

# after
class MyExp(Experiment):
    def _get_recorder(self, recorder_id=None, recorder_name=None):
        run = self._client.get_run(recorder_id) if recorder_id else self._find_by_name(recorder_name)
        if run is None:
            raise ValueError('No valid recorder has been found')
        return MyRecorder(self.id, self._uri, mlflow_run=run)
Defensive patterns

Strategy: type-guard

Validate before calling

from qlib.workflow.exp import Experiment
assert exp.__class__._get_recorder is not Experiment._get_recorder, 'record lookup not implemented'

Type guard

def has_recorder_lookup(exp) -> bool:
    from qlib.workflow.exp import Experiment
    return exp.__class__._get_recorder is not Experiment._get_recorder

Prevention

When it happens

Trigger: get_recorder(...) on a base/incomplete Experiment, which internally calls self._get_recorder; direct exp._get_recorder(...) calls in custom code; a subclass overriding get_recorder but not the private _get_recorder.

Common situations: Implementing a custom tracking backend and missing the private lookup method even though the public get_recorder exists; test harnesses exercising the abstract interface.

Related errors


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