{"record":{"id":"df54e61ec4a835e3","repo":"microsoft/qlib","slug":"no-valid-recorder-has-been-found-please-make-sure-df54e6","errorCode":null,"errorMessage":"No valid recorder has been found, please make sure the input recorder name is correct.","messagePattern":"No valid recorder has been found, please make sure the input recorder name is correct\\.","errorType":"exception","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"qlib/workflow/exp.py","lineNumber":315,"sourceCode":"        ), \"Please input at least one of recorder id or name before retrieving recorder.\"\r\n        if recorder_id is not None:\r\n            try:\r\n                run = self._client.get_run(recorder_id)\r\n                recorder = MLflowRecorder(self.id, self._uri, mlflow_run=run)\r\n                return recorder\r\n            except MlflowException as mlflow_exp:\r\n                raise ValueError(\r\n                    \"No valid recorder has been found, please make sure the input recorder id is correct.\"\r\n                ) from mlflow_exp\r\n        elif recorder_name is not None:\r\n            logger.warning(\r\n                f\"Please make sure the recorder name {recorder_name} is unique, we will only return the latest recorder if there exist several matched the given name.\"\r\n            )\r\n            recorders = self.list_recorders()\r\n            for rid in recorders:\r\n                if recorders[rid].name == recorder_name:\r\n                    return recorders[rid]\r\n            raise ValueError(\"No valid recorder has been found, please make sure the input recorder name is correct.\")\r\n\r\n    def search_records(self, **kwargs):\r\n        filter_string = \"\" if kwargs.get(\"filter_string\") is None else kwargs.get(\"filter_string\")\r\n        run_view_type = 1 if kwargs.get(\"run_view_type\") is None else kwargs.get(\"run_view_type\")\r\n        max_results = 100000 if kwargs.get(\"max_results\") is None else kwargs.get(\"max_results\")\r\n        order_by = kwargs.get(\"order_by\")\r\n\r\n        return self._client.search_runs([self.id], filter_string, run_view_type, max_results, order_by)\r\n\r\n    def delete_recorder(self, recorder_id=None, recorder_name=None):\r\n        assert (\r\n            recorder_id is not None or recorder_name is not None\r\n        ), \"Please input a valid recorder id or name before deleting.\"\r\n        try:\r\n            if recorder_id is not None:\r\n                self._client.delete_run(recorder_id)\r\n            else:\r\n                recorder = self._get_recorder(recorder_name=recorder_name)\r","sourceCodeStart":297,"sourceCodeEnd":333,"githubUrl":"https://github.com/microsoft/qlib/blob/79633dd9506ea689e5400dea0197717b5b3d74b7/qlib/workflow/exp.py#L297-L333","documentation":"MLflowExperiment._get_recorder resolves by name by scanning list_recorders() for the first (latest, since MLflow sorts by start_time DESC) run whose name matches; if none matches, this ValueError is raised. Note recorder names are not unique in MLflow, so only the latest match is ever returned.","triggerScenarios":"exp.get_recorder(recorder_name='nnmodel') when no run in this experiment is named 'nnmodel'; name differs by case/spacing ('NNModel' vs 'nnmodel'); the matching run lives in a different experiment; a name given where an id was expected.","commonSituations":"Assuming the recorder_name equals the experiment name or the model class; renaming recorders in code but querying with old names; multiple experiments each with similarly named runs and querying the wrong one.","solutions":["List actual names first: {r.name for r in exp.list_recorders().values()} and use an exact string.","Prefer recorder_id for unambiguous retrieval; names only give the latest match.","Confirm you are in the right experiment (R.get_exp) before the name lookup."],"exampleFix":"# before\nrec = exp.get_recorder(recorder_name='lit_gbm')  # ValueError\n\n# after\nnames = {r.name: rid for rid, r in exp.list_recorders().items()}\nrec = exp.get_recorder(recorder_id=names['lgb_model'])  # exact id lookup","handlingStrategy":"validation","validationCode":"name2rid = {r.name: rid for rid, r in exp.list_recorders().items()}\nif recorder_name not in name2rid:\n    raise KeyError(f'no recorder named {recorder_name!r}; names: {sorted(set(name2rid))}')\nrec = exp.get_recorder(recorder_id=name2rid[recorder_name])","typeGuard":"def recorder_name_exists(exp, name: str) -> bool:\n    return any(r.name == name for r in exp.list_recorders().values())","tryCatchPattern":"try:\n    rec = exp.get_recorder(recorder_name=name)\nexcept ValueError:\n    rec = exp.get_recorder(recorder_id=latest_rid)  # fallback to id-based retrieval","preventionTips":["Prefer recorder_id over name; names are not unique and only the latest match is returned.","Compare names exactly (case/whitespace) against list_recorders output."],"tags":["qlib","mlflow","recorder","name-lookup","value-error"],"backgroundTag":null,"analyzedSha":"79633dd9506ea689e5400dea0197717b5b3d74b7","analyzedAt":"2026-08-15T07:01:27.511Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}