microsoft/qlib · error · NotImplementedError

Please implement the `end` method.

Error message

Please implement the `end` method.

What it means

Experiment.end(recorder_status) is an abstract stub in qlib/workflow/exp.py that raises NotImplementedError. It is meant to be overridden by concrete backends such as MLflowExperiment, where ending an experiment sets its active recorder's status (SCHEDULED, RUNNING, FINISHED, FAILED). The error signals an abstract or incompletely implemented Experiment subclass was used.

Source

Thrown at qlib/workflow/exp.py:72

        resume : bool
            whether to resume the first recorder

        Returns
        -------
        An active recorder.
        """
        raise NotImplementedError(f"Please implement the `start` method.")

    def end(self, recorder_status=Recorder.STATUS_S):
        """
        End the experiment.

        Parameters
        ----------
        recorder_status : str
            the status the recorder to be set with when ending (SCHEDULED, RUNNING, FINISHED, FAILED).
        """
        raise NotImplementedError(f"Please implement the `end` method.")

    def create_recorder(self, recorder_name=None):
        """
        Create a recorder for each experiment.

        Parameters
        ----------
        recorder_name : str
            the name of the recorder to be created.

        Returns
        -------
        A recorder object.
        """
        raise NotImplementedError(f"Please implement the `create_recorder` method.")

    def search_records(self, **kwargs):
        """

View on GitHub (pinned to 79633dd950)

Solutions

  1. Use the shipped MLflowExperiment via qlib.init() instead of a hand-rolled Experiment.
  2. In your subclass, implement end(self, recorder_status=Recorder.STATUS_S) to deactivate the experiment and finalize its recorder.
  3. Audit your subclass against every method on the base Experiment (start, end, create_recorder, search_records, delete_recorder, _get_recorder, list_recorders).

Example fix

# before
class MyExp(Experiment):
    def start(self, **kw):
        ...
exp.end()  # NotImplementedError from base end

# after
class MyExp(Experiment):
    def start(self, **kw): ...
    def end(self, recorder_status=Recorder.STATUS_S):
        # finalize recorder with recorder_status
        ...
Defensive patterns

Strategy: type-guard

Validate before calling

from qlib.workflow.exp import Experiment
assert exp.__class__.end is not Experiment.end, 'end() not implemented by this backend'

Type guard

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

Prevention

When it happens

Trigger: Calling exp.end() on a bare Experiment instance; R.end_exp() routing to a custom Experiment subclass that does not override end; a subclass that overrides end_exp (manager-level) but not end (experiment-level).

Common situations: Building a custom tracking backend and implementing only the manager side (ExpManager) while leaving the Experiment side abstract; renaming methods while refactoring; upgrading qlib where the abstract interface gained methods.

Related errors


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