microsoft/qlib · error · NotImplementedError
Please implement the `save_objects` method.
Error message
Please implement the `save_objects` method.
What it means
Recorder is the abstract base of qlib's recorder system (MLflowRecorder is the concrete implementation); save_objects is the method that persists artifacts (prediction files, model checkpoints) to the recorder's artifact URI. The base class raises NotImplementedError by design. Hitting it means save_objects was called on the base Recorder — i.e. no concrete backend was ever selected or a custom subclass is incomplete.
Source
Thrown at qlib/workflow/recorder.py:88
def set_recorder_name(self, rname):
self.recorder_name = rname
def save_objects(self, local_path=None, artifact_path=None, **kwargs):
"""
Save objects such as prediction file or model checkpoints to the artifact URI. User
can save object through keywords arguments (name:value).
Please refer to the docs of qlib.workflow:R.save_objects
Parameters
----------
local_path : str
if provided, them save the file or directory to the artifact URI.
artifact_path=None : str
the relative path for the artifact to be stored in the URI.
"""
raise NotImplementedError(f"Please implement the `save_objects` method.")
def load_object(self, name):
"""
Load objects such as prediction file or model checkpoints.
Parameters
----------
name : str
name of the file to be loaded.
Returns
-------
The saved object.
"""
raise NotImplementedError(f"Please implement the `load_object` method.")
def start_run(self):
"""
View on GitHub (pinned to 79633dd950)
Solutions
- Use the standard path: R.start(experiment_name=...) inside qlib.init context so you get an MLflowRecorder, whose save_objects works
- If subclassing Recorder, implement save_objects(self, local_path=None, artifact_path=None, **kwargs) plus every other abstract method (load_object, start_run, end_run, log_params, ...)
- Check how the recorder was obtained — R.get_recorder() on an active run returns a concrete MLflowRecorder; constructing Recorder(...) by hand does not
Example fix
# before
from qlib.workflow.recorder import Recorder
rec = Recorder(...) # abstract
rec.save_objects(pred=pred) # NotImplementedError
# after
with R.start('my_exp'):
rec = R.get_recorder()
rec.save_objects(pred=pred) Defensive patterns
Strategy: type-guard
Validate before calling
from qlib.workflow.recorder import Recorder
from qlib.workflow import R
def get_live_recorder():
with R.start(experiment_name='my_exp'):
rec = R.get_recorder()
assert not isinstance(rec, type(None)) and type(rec).save_objects is not Recorder.save_objects
return rec Type guard
from qlib.workflow.recorder import Recorder
def is_concrete_recorder(rec) -> bool:
return type(rec).save_objects is not Recorder.save_objects Try / catch
try:
rec.save_objects(pred=pred)
except NotImplementedError as e:
raise TypeError(f'{type(rec).__name__} is the abstract Recorder; obtain it via R.start/R.get_recorder') from e Prevention
- Never instantiate Recorder directly; always get recorders from QlibRecorder (R)
- In custom Recorder subclasses, implement every abstract method before registering it
- Type-check received recorders at API boundaries in framework code
When it happens
Trigger: Instantiating qlib.workflow.recorder.Recorder directly and calling save_objects; a custom Recorder subclass missing the save_objects override being registered via QlibRecorder.set_uri/register; code that fetched a recorder as the abstract type from a misconfigured exp_manager/recorder factory.
Common situations: Attempting to add a new tracking backend to qlib by subclassing Recorder; unit tests using the base class as a stand-in; factory/registration bugs where the MLflowRecorder was not chosen (e.g. bad uri scheme).
Related errors
- Please implement the `create_recorder` method.
- Please implement the `delete_recorder` method.
- Please implement the `_get_recorder` method
- Please implement the `list_recorders` method.
- Please implement the `load_object` method.
AI-assisted analysis of microsoft/qlib@79633dd950 (2026-08-15).
Data as JSON: /api/errors/552f2683f7ed460b.
Report an issue: GitHub.