microsoft/qlib · error · NotImplementedError

Please implement the `end_exp` method.

Error message

Please implement the `end_exp` method.

What it means

ExpManager.end_exp clears _active_exp_uri then delegates to _end_exp, an abstract hook whose base body raises NotImplementedError. It fires when the active manager is the base ExpManager or an incomplete subclass, i.e. no backend logic exists to end the experiment and finalize its recorder status.

Source

Thrown at qlib/workflow/expm.py:117

        """
        End an active experiment.

        Maintaining `_active_exp_uri` is included in end_exp, remaining implementation should be included in _end_exp in subclass

        Parameters
        ----------
        experiment_name : str
            name of the active experiment.
        recorder_status : str
            the status of the active recorder of the experiment.
        """
        self._active_exp_uri = None
        # The subclass may set the underlying uri back.
        # So setting `_active_exp_uri` come before `_end_exp`
        self._end_exp(recorder_status=recorder_status, **kwargs)

    def _end_exp(self, recorder_status: Text = Recorder.STATUS_S, **kwargs):
        raise NotImplementedError(f"Please implement the `end_exp` method.")

    def create_exp(self, experiment_name: Optional[Text] = None):
        """
        Create an experiment.

        Parameters
        ----------
        experiment_name : str
            the experiment name, which must be unique.

        Returns
        -------
        An experiment object.

        Raise
        -----
        ExpAlreadyExistError
        """

View on GitHub (pinned to 79633dd950)

Solutions

  1. Use the default MLflowExpManager via qlib.init().
  2. Implement _end_exp(self, recorder_status=Recorder.STATUS_S, **kwargs) in your subclass to close the active experiment.
  3. Ensure the whole hook set (_start_exp, _end_exp, create_exp, _get_exp, delete_exp, list_experiments, search_records) is implemented.

Example fix

# before
class MyManager(ExpManager):
    pass
R.end_exp()  # NotImplementedError from base _end_exp

# after
class MyManager(ExpManager):
    def _end_exp(self, recorder_status=Recorder.STATUS_S, **kwargs):
        self.active_experiment.set_status(recorder_status)
Defensive patterns

Strategy: type-guard

Validate before calling

from qlib.workflow.expm import ExpManager
assert R.exp_manager.__class__._end_exp is not ExpManager._end_exp, '_end_exp not implemented'

Type guard

def manager_can_end(mgr) -> bool:
    from qlib.workflow.expm import ExpManager
    return mgr.__class__._end_exp is not ExpManager._end_exp

Prevention

When it happens

Trigger: R.end_exp() with a custom or bare exp_manager lacking _end_exp; calling end_exp after replacing the default MLflowExpManager in C['exp_manager'].

Common situations: Skeleton custom tracking managers that implement start but not end; test doubles subclassing ExpManager without full coverage of hooks.

Related errors


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