{"record":{"id":"d0e16d4a7dfa8365","repo":"microsoft/qlib","slug":"please-make-sure-the-recorder-has-been-created-and","errorCode":null,"errorMessage":"Please make sure the recorder has been created and started properly before getting artifact uri.","messagePattern":"Please make sure the recorder has been created and started properly before getting artifact uri\\.","errorType":"exception","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"qlib/workflow/recorder.py","lineNumber":331,"sourceCode":"        return self._artifact_uri\r\n\r\n    def get_local_dir(self):\r\n        \"\"\"\r\n        This function will return the directory path of this recorder.\r\n        \"\"\"\r\n        if self.artifact_uri is not None:\r\n            if platform.system() == \"Windows\":\r\n                local_dir_path = Path(self.artifact_uri.lstrip(\"file:\").lstrip(\"/\")).parent\r\n            else:\r\n                local_dir_path = Path(self.artifact_uri.lstrip(\"file:\")).parent\r\n            local_dir_path = str(local_dir_path.resolve())\r\n            if os.path.isdir(local_dir_path):\r\n                return local_dir_path\r\n            else:\r\n                raise RuntimeError(\"This recorder is not saved in the local file system.\")\r\n\r\n        else:\r\n            raise ValueError(\r\n                \"Please make sure the recorder has been created and started properly before getting artifact uri.\"\r\n            )\r\n\r\n    def start_run(self):\r\n        # set the tracking uri\r\n        mlflow.set_tracking_uri(self.uri)\r\n        # start the run\r\n        run = mlflow.start_run(self.id, self.experiment_id, self.name)\r\n        # save the run id and artifact_uri\r\n        self.id = run.info.run_id\r\n        self._artifact_uri = run.info.artifact_uri\r\n        self.start_time = datetime.now().strftime(\"%Y-%m-%d %H:%M:%S\")\r\n        self.status = Recorder.STATUS_R\r\n        logger.info(f\"Recorder {self.id} starts running under Experiment {self.experiment_id} ...\")\r\n\r\n        # NOTE: making logging async.\r\n        # - This may cause delay when uploading results\r\n        # - The logging time may not be accurate\r","sourceCodeStart":313,"sourceCodeEnd":349,"githubUrl":"https://github.com/microsoft/qlib/blob/79633dd9506ea689e5400dea0197717b5b3d74b7/qlib/workflow/recorder.py#L313-L349","documentation":"Raised by Recorder.local_path when self.artifact_uri is None. The artifact URI is only populated after the recorder (an MLflow run) has been created and started; calling local_path on a recorder that was never started leaves artifact_uri None, so there is nothing to resolve into a local directory path.","triggerScenarios":"Calling recorder.local_path (directly or via APIs that save/read artifacts locally) on a Recorder instance obtained before start_run()/create_recorder was committed, e.g. R.get_recorder() on a fresh experiment where the run failed to start, or a Recorder constructed manually without starting.","commonSituations":"Experiment was created but the recorder start threw earlier (e.g. MLflow tracking server unreachable), user reuses a stale Recorder object after the run crashed, or the tracking backend is remote (the sibling RuntimeError branch also fires when the artifact dir is not local).","solutions":["Ensure the recorder is started before touching artifacts: use exp.get_recorder() only after R.start() and a successful run, or call recorder.start_run() first.","Check recorder.artifact_uri is not None before calling local_path; if None, re-create the recorder via R.get_exp().create_recorder(...) + start_run().","If the run was created through qlib.workflow.R, verify the MLflow tracking URI is reachable so start_run() actually persisted the run.","If you truly have a valid run id, reload the recorder from the tracking store (e.g. MLflow client.get_run(id).info.artifact_uri) instead of using the un-started object."],"exampleFix":"// before\nrecorder = exp.get_recorder()\npath = recorder.local_path  # ValueError if run never started\n\n// after\nrecorder = exp.get_recorder()\nif recorder.artifact_uri is None:\n    recorder.start_run()\npath = recorder.local_path","handlingStrategy":"validation","validationCode":"if recorder.artifact_uri is None:\n    raise RuntimeError(f\"Recorder {recorder.id} not started; artifact_uri is None\")\npath = recorder.local_path","typeGuard":null,"tryCatchPattern":"try:\n    path = recorder.local_path\nexcept ValueError as e:\n    if \"artifact uri\" in str(e):\n        recorder.start_run()\n        path = recorder.local_path\n    else:\n        raise","preventionTips":["Always obtain recorders via R.get_recorder() after a completed run, not from a fresh experiment object.","Assert recorder.artifact_uri is not None before any artifact/local-path access.","Confirm the MLflow tracking server is reachable before starting workflows."],"tags":["qlib","mlflow","recorder","artifact","workflow"],"backgroundTag":null,"analyzedSha":"79633dd9506ea689e5400dea0197717b5b3d74b7","analyzedAt":"2026-08-15T07:01:27.511Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}