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

  1. Run deletion through the MLflow-backed experiment obtained from R.get_exp().
  2. Implement delete_recorder(self, recorder_id) in your subclass, calling the backend's delete API.
  3. 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

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


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