{"record":{"id":"5869bf4f21e6f8f0","repo":"microsoft/qlib","slug":"this-recordtemp-did-not-set-recorder-yet","errorCode":null,"errorMessage":"This RecordTemp did not set recorder yet.","messagePattern":"This RecordTemp did not set recorder yet\\.","errorType":"exception","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"qlib/workflow/record_temp.py","lineNumber":65,"sourceCode":"        return \"/\".join(names)\n\n    def save(self, **kwargs):\n        \"\"\"\n        It behaves the same as self.recorder.save_objects.\n        But it is an easier interface because users don't have to care about `get_path` and `artifact_path`\n        \"\"\"\n        art_path = self.get_path()\n        if art_path == \"\":\n            art_path = None\n        self.recorder.save_objects(artifact_path=art_path, **kwargs)\n\n    def __init__(self, recorder):\n        self._recorder = recorder\n\n    @property\n    def recorder(self):\n        if self._recorder is None:\n            raise ValueError(\"This RecordTemp did not set recorder yet.\")\n        return self._recorder\n\n    def generate(self, **kwargs):\n        \"\"\"\n        Generate certain records such as IC, backtest etc., and save them.\n\n        Parameters\n        ----------\n        kwargs\n\n        Return\n        ------\n        \"\"\"\n        raise NotImplementedError(f\"Please implement the `generate` method.\")\n\n    def load(self, name: str, parents: bool = True):\n        \"\"\"\n        It behaves the same as self.recorder.load_object.","sourceCodeStart":47,"sourceCodeEnd":83,"githubUrl":"https://github.com/microsoft/qlib/blob/79633dd9506ea689e5400dea0197717b5b3d74b7/qlib/workflow/record_temp.py#L47-L83","documentation":"RecordTemp.recorder is a property that raises ValueError when self._recorder is None. RecordTemp (and subclasses like SignalRecord, PortAnaRecord) must be bound to a QlibRecorder to know where to save artifacts; a None recorder means generate/save/load cannot proceed, so the property fails fast.","triggerScenarios":"Constructing RecordTemp(recorder=None) or a subclass whose __init__ propagates recorder=None; using a record template before R.start() created a recorder; passing the result of a failed R.get_recorder() call; deserializing/pickling a record temp without its recorder.","commonSituations":"Creating record objects manually outside a with R.start(...) context; recorder lookup returning None and being passed through unchecked; forgetting to attach a recorder when composing custom record lists for the 'record' field in a workflow config.","solutions":["Create/start a recorder first (R.start(...) or R.get_recorder(...)) and pass the live recorder into the record temp constructor","Guard the lookup: only build the RecordTemp when the recorder is not None","Check the 'record' section of your workflow config — record classes listed there are instantiated with the active recorder; make sure a run is active"],"exampleFix":"# before\nwith R.start('my_exp'):\n    pass\nrec = R.get_recorder()          # may be None if no run matched\nsr = SignalRecord(recorder=rec) # rec is None -> later ValueError\n\n# after\nwith R.start('my_exp'):\n    rec = R.get_recorder()\n    assert rec is not None, 'no active recorder'\n    sr = SignalRecord(recorder=rec)\n    sr.generate()","handlingStrategy":"validation","validationCode":"from qlib.workflow import R\n\ndef get_record(recorder, record_cls):\n    if recorder is None:\n        raise ValueError('no active recorder; call R.start(...) first')\n    return record_cls(recorder=recorder)","typeGuard":"def is_live_recorder(rec) -> bool:\n    return rec is not None and hasattr(rec, 'save_objects') and getattr(rec, 'id', None) is not None","tryCatchPattern":"try:\n    rt.recorder  # property access\nexcept ValueError as e:\n    raise RuntimeError('record temp has no recorder; recreate it inside R.start context') from e","preventionTips":["Create record temps only inside `with R.start(...)` blocks","Check R.get_recorder() results for None before passing them on","When listing record classes in workflow configs, keep them as strings resolved after the run starts"],"tags":["qlib","recorder","record-temp","validation"],"backgroundTag":null,"analyzedSha":"79633dd9506ea689e5400dea0197717b5b3d74b7","analyzedAt":"2026-08-15T07:01:27.511Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}