{"record":{"id":"27df117d4d4335ae","repo":"microsoft/qlib","slug":"model-is-not-fitted-yet-27df11","errorCode":null,"errorMessage":"model is not fitted yet!","messagePattern":"model is not fitted yet!","errorType":"exception","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"qlib/contrib/model/xgboost.py","lineNumber":73,"sourceCode":"\n        dtrain = xgb.DMatrix(x_train.values, label=y_train_1d, weight=w_train)\n        dvalid = xgb.DMatrix(x_valid.values, label=y_valid_1d, weight=w_valid)\n        self.model = xgb.train(\n            self._params,\n            dtrain=dtrain,\n            num_boost_round=num_boost_round,\n            evals=[(dtrain, \"train\"), (dvalid, \"valid\")],\n            early_stopping_rounds=early_stopping_rounds,\n            verbose_eval=verbose_eval,\n            evals_result=evals_result,\n            **kwargs,\n        )\n        evals_result[\"train\"] = list(evals_result[\"train\"].values())[0]\n        evals_result[\"valid\"] = list(evals_result[\"valid\"].values())[0]\n\n    def predict(self, dataset: DatasetH, segment: Union[Text, slice] = \"test\"):\n        if self.model is None:\n            raise ValueError(\"model is not fitted yet!\")\n        x_test = dataset.prepare(segment, col_set=\"feature\", data_key=DataHandlerLP.DK_I)\n        return pd.Series(self.model.predict(xgb.DMatrix(x_test)), index=x_test.index)\n\n    def get_feature_importance(self, *args, **kwargs) -> pd.Series:\n        \"\"\"get feature importance\n\n        Notes\n        -------\n            parameters reference:\n                https://xgboost.readthedocs.io/en/latest/python/python_api.html#xgboost.Booster.get_score\n        \"\"\"\n        return pd.Series(self.model.get_score(*args, **kwargs)).sort_values(ascending=False)\n","sourceCodeStart":55,"sourceCodeEnd":86,"githubUrl":"https://github.com/microsoft/qlib/blob/79633dd9506ea689e5400dea0197717b5b3d74b7/qlib/contrib/model/xgboost.py#L55-L86","documentation":"Raised by XGBModel.predict when self.model is None, which is its initial value before fit() successfully runs xgb.train and assigns the booster. It is the standard not-fitted guard for the XGBoost wrapper, mirroring sklearn's NotFittedError semantics with a ValueError.","triggerScenarios":"Calling predict(dataset) on an XGBModel that never had fit() called; calling predict after fit() failed before self.model was assigned (e.g. empty data error, bad params); using a model object restored from config without retraining or without loading a saved booster.","commonSituations":"Running a backtest workflow with a model dict that instantiates XGBModel but never trains; fit() raised earlier in a pipeline and the exception was swallowed; separating train and predict scripts while sharing only the config, not the trained booster.","solutions":["Call model.fit(dataset, ...) to completion before predict().","If fit() failed earlier, fix that failure first; the booster is only assigned at the end of a successful fit.","To reuse a trained model in another process, persist the fitted model object (pickle the whole XGBModel or its booster) and restore it, rather than re-instantiating from config alone."],"exampleFix":"# before\nmodel = XGBModel()\nmodel.predict(dataset)  # ValueError: model is not fitted yet!\n\n# after\nmodel = XGBModel()\nmodel.fit(dataset, num_boost_round=200)\nmodel.predict(dataset)","handlingStrategy":"validation","validationCode":"if model.model is None:  # booster not yet trained\n    raise RuntimeError(\"XGBModel.fit() must run before predict()\")\npreds = model.predict(dataset)","typeGuard":"def is_fitted_xgb(model) -> bool:\n    return getattr(model, \"model\", None) is not None","tryCatchPattern":"try:\n    pred = model.predict(dataset)\nexcept ValueError as e:\n    if \"not fitted\" in str(e):\n        model.fit(dataset, num_boost_round=n_rounds)\n        pred = model.predict(dataset)\n    else:\n        raise","preventionTips":["Gate inference pipelines on model.model is not None.","Persist fitted XGBModel objects (pickle) for reuse instead of config-only re-instantiation.","Fail the whole pipeline when fit() errors; never continue to predict."],"tags":["qlib","xgboost","lifecycle","state","predict"],"backgroundTag":null,"analyzedSha":"79633dd9506ea689e5400dea0197717b5b3d74b7","analyzedAt":"2026-08-15T07:01:27.511Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}