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
- Use MLflowExperiment (via qlib.init defaults) whose _get_recorder resolves runs through MLflow.
- In a custom subclass, implement _get_recorder(self, recorder_id=None, recorder_name=None) returning your Recorder or raising ValueError when not found.
- 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
- Use the public get_recorder API; it surfaces clear ValueError messages from concrete backends.
- Custom backends must implement the private hooks, not just public wrappers.
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
- Please implement the `create_recorder` method.
- Please implement the `delete_recorder` method.
- Please implement the `list_recorders` method.
- Please implement the `_get_exp` method
- Please implement the `save_objects` method.
AI-assisted analysis of microsoft/qlib@79633dd950 (2026-08-15).
Data as JSON: /api/errors/d8683341a2b70fb7.
Report an issue: GitHub.