microsoft/qlib · error · ValueError

Please make sure the recorder has been created and started…

Error message

Please make sure the recorder has been created and started properly before getting artifact uri.

What it means

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.

Solutions

  1. 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.
  2. 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().
  3. If the run was created through qlib.workflow.R, verify the MLflow tracking URI is reachable so start_run() actually persisted the run.
  4. 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.

Example fix

// before
recorder = exp.get_recorder()
path = recorder.local_path  # ValueError if run never started

// after
recorder = exp.get_recorder()
if recorder.artifact_uri is None:
    recorder.start_run()
path = recorder.local_path
Defensive patterns

Strategy: validation

Validate before calling

if recorder.artifact_uri is None:
    raise RuntimeError(f"Recorder {recorder.id} not started; artifact_uri is None")
path = recorder.local_path

Try / catch

try:
    path = recorder.local_path
except ValueError as e:
    if "artifact uri" in str(e):
        recorder.start_run()
        path = recorder.local_path
    else:
        raise

Prevention

When it happens

Trigger: 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.

Common situations: 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).

Related errors


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

Appendix: source

Thrown at qlib/workflow/recorder.py:331

        return self._artifact_uri

    def get_local_dir(self):
        """
        This function will return the directory path of this recorder.
        """
        if self.artifact_uri is not None:
            if platform.system() == "Windows":
                local_dir_path = Path(self.artifact_uri.lstrip("file:").lstrip("/")).parent
            else:
                local_dir_path = Path(self.artifact_uri.lstrip("file:")).parent
            local_dir_path = str(local_dir_path.resolve())
            if os.path.isdir(local_dir_path):
                return local_dir_path
            else:
                raise RuntimeError("This recorder is not saved in the local file system.")

        else:
            raise ValueError(
                "Please make sure the recorder has been created and started properly before getting artifact uri."
            )

    def start_run(self):
        # set the tracking uri
        mlflow.set_tracking_uri(self.uri)
        # start the run
        run = mlflow.start_run(self.id, self.experiment_id, self.name)
        # save the run id and artifact_uri
        self.id = run.info.run_id
        self._artifact_uri = run.info.artifact_uri
        self.start_time = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
        self.status = Recorder.STATUS_R
        logger.info(f"Recorder {self.id} starts running under Experiment {self.experiment_id} ...")

        # NOTE: making logging async.
        # - This may cause delay when uploading results
        # - The logging time may not be accurate

View on GitHub (pinned to 79633dd950)