microsoft/qlib · error · NotImplementedError
Please implement the `delete_recorder` method.
Error message
Please implement the `delete_recorder` method.
What it means
Experiment.delete_recorder is an abstract stub in the Experiment interface; it must remove the recorder with the given recorder_id. The NotImplementedError fires when the base class (or an incomplete subclass) is used, meaning the deletion never reached a real tracking backend.
Source
Thrown at qlib/workflow/exp.py:112
Returns
-------
A pandas.DataFrame of records, where each metric, parameter, and tag
are expanded into their own columns named metrics.*, params.*, and tags.*
respectively. For records that don't have a particular metric, parameter, or tag, their
value will be (NumPy) Nan, None, or None respectively.
"""
raise NotImplementedError(f"Please implement the `search_records` method.")
def delete_recorder(self, recorder_id):
"""
Create a recorder for each experiment.
Parameters
----------
recorder_id : str
the id of the recorder to be deleted.
"""
raise NotImplementedError(f"Please implement the `delete_recorder` method.")
def get_recorder(self, recorder_id=None, recorder_name=None, create: bool = True, start: bool = False) -> Recorder:
"""
Retrieve a Recorder for user. When user specify recorder id and name, the method will try to return the
specific recorder. When user does not provide recorder id or name, the method will try to return the current
active recorder. The `create` argument determines whether the method will automatically create a new recorder
according to user's specification if the recorder hasn't been created before.
* If `create` is True:
* If `active recorder` exists:
* no id or name specified, return the active recorder.
* if id or name is specified, return the specified recorder. If no such exp found, create a new recorder with given id or name. If `start` is set to be True, the recorder is set to be active.
* If `active recorder` not exists:
* no id or name specified, create a new recorder.
View on GitHub (pinned to 79633dd950)
Solutions
- Run deletion through the MLflow-backed experiment obtained from R.get_exp().
- Implement delete_recorder(self, recorder_id) in your subclass, calling the backend's delete API.
- Alternatively delete the run directly in the backend (e.g. mlflow client delete_run) if you bypass qlib.
Example fix
# before
Experiment('1', 'e').delete_recorder('run_id') # NotImplementedError
# after
exp = R.get_exp(experiment_name='my_exp')
exp.delete_recorder('run_id') # MLflowExperiment implementation Defensive patterns
Strategy: type-guard
Validate before calling
from qlib.workflow.exp import Experiment assert exp.__class__.delete_recorder is not Experiment.delete_recorder, 'deletion unsupported by backend'
Type guard
def can_delete_recorders(exp) -> bool:
from qlib.workflow.exp import Experiment
return exp.__class__.delete_recorder is not Experiment.delete_recorder Prevention
- Run deletions only on experiments from R.get_exp().
- Make cleanup scripts check the capability before calling delete.
When it happens
Trigger: exp.delete_recorder(recorder_id) on a directly built Experiment; custom backend subclass without a delete_recorder override; R.delete_recorder(...) routed through such a subclass.
Common situations: Cleanup scripts that iterate experiments calling delete on each; writing a minimal custom backend for logging only and later needing deletion; subclasses copied from examples that omit delete methods.
Related errors
- Please implement the `create_recorder` method.
- Please implement the `_get_recorder` method
- Please implement the `list_recorders` method.
- Please implement the `delete_exp` method.
- Please implement the `save_objects` method.
AI-assisted analysis of microsoft/qlib@79633dd950 (2026-08-15).
Data as JSON: /api/errors/c521cbb35ab319b8.
Report an issue: GitHub.