microsoft/qlib · error · NotImplementedError

Please implement the `set_online_tag` method.

Error message

Please implement the `set_online_tag` method.

What it means

OnlineTool.set_online_tag is an abstract method of the OnlineTool base class (qlib/workflow/online/utils.py). The base raises NotImplementedError to force concrete tools to define how a tag (ONLINE_TAG / OFFLINE_TAG) is written onto one or more recorders. Hitting it means your code called set_online_tag on the base class or on a subclass that did not override it.

Source

Thrown at qlib/workflow/online/utils.py:42

    ONLINE_KEY = "online_status"  # the online status key in recorder
    ONLINE_TAG = "online"  # the 'online' model
    OFFLINE_TAG = "offline"  # the 'offline' model, not for online serving

    def __init__(self):
        """
        Init OnlineTool.
        """
        self.logger = get_module_logger(self.__class__.__name__)

    def set_online_tag(self, tag, recorder: Union[list, object]):
        """
        Set `tag` to the model to sign whether online.

        Args:
            tag (str): the tags in `ONLINE_TAG`, `OFFLINE_TAG`
            recorder (Union[list,object]): the model's recorder
        """
        raise NotImplementedError(f"Please implement the `set_online_tag` method.")

    def get_online_tag(self, recorder: object) -> str:
        """
        Given a model recorder and return its online tag.

        Args:
            recorder (Object): the model's recorder

        Returns:
            str: the online tag
        """
        raise NotImplementedError(f"Please implement the `get_online_tag` method.")

    def reset_online_tag(self, recorder: Union[list, object]):
        """
        Offline all models and set the recorders to 'online'.

        Args:

View on GitHub (pinned to 79633dd950)

Solutions

  1. Use the built-in OnlineToolR (recorder-based implementation) instead of the abstract OnlineTool: OnlineToolR(default_exp_name='...')
  2. If you subclass OnlineTool, implement set_online_tag(self, tag, recorder) handling both a single recorder and a list
  3. Verify you are not accidentally instantiating the base class in your strategy's __init__ (OnlineStrategy defaults self.tool = OnlineTool())

Example fix

# before
tool = OnlineTool()              # abstract
tool.set_online_tag('online', rec)  # NotImplementedError

# after
tool = OnlineToolR(default_exp_name='my_experiment')
tool.set_online_tag('online', rec)
Defensive patterns

Strategy: type-guard

Validate before calling

from qlib.workflow.online.utils import OnlineTool, OnlineToolR

def make_tool(exp_name=None):
    # never hand out the abstract OnlineTool
    return OnlineToolR(default_exp_name=exp_name)

Type guard

from qlib.workflow.online.utils import OnlineTool

def is_concrete_tool(tool) -> bool:
    return type(tool).set_online_tag is not OnlineTool.set_online_tag

Try / catch

try:
    tool.set_online_tag('online', rec)
except NotImplementedError as e:
    raise TypeError(f'{type(tool).__name__} is not a usable OnlineTool: {e}') from e

Prevention

When it happens

Trigger: Instantiating raw OnlineTool() and calling set_online_tag(tag, recorder); subclassing OnlineTool (e.g. for a custom backend) without implementing set_online_tag; a strategy constructed with a custom tool whose tag methods were forgotten, so reset_online_tag / prepare flows crash here.

Common situations: Writing a custom OnlineTool for a non-recorder storage backend; copying OnlineToolR and stripping methods; using OnlineTool base directly instead of OnlineToolR.

Related errors


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