microsoft/qlib · error · ValueError

Empty data from dataset, please check your dataset config.

Error message

Empty data from dataset, please check your dataset config.

What it means

Thrown by CatBoostModel.fit when dataset.prepare returns an empty train or valid DataFrame. CatBoost requires both a training and a validation split (the fit call requests ["train", "valid"] with DK_L data) because it uses eval_set with use_best_model=True and early stopping. If either segment yields zero rows after the handler's learn-time processing, the model refuses to train.

Source

Thrown at qlib/contrib/model/catboost_model.py:44

        self.model = None

    def fit(
        self,
        dataset: DatasetH,
        num_boost_round=1000,
        early_stopping_rounds=50,
        verbose_eval=20,
        evals_result=dict(),
        reweighter=None,
        **kwargs,
    ):
        df_train, df_valid = dataset.prepare(
            ["train", "valid"],
            col_set=["feature", "label"],
            data_key=DataHandlerLP.DK_L,
        )
        if df_train.empty or df_valid.empty:
            raise ValueError("Empty data from dataset, please check your dataset config.")
        x_train, y_train = df_train["feature"], df_train["label"]
        x_valid, y_valid = df_valid["feature"], df_valid["label"]

        # CatBoost needs 1D array as its label
        if y_train.values.ndim == 2 and y_train.values.shape[1] == 1:
            y_train_1d, y_valid_1d = np.squeeze(y_train.values), np.squeeze(y_valid.values)
        else:
            raise ValueError("CatBoost doesn't support multi-label training")

        if reweighter is None:
            w_train = None
            w_valid = None
        elif isinstance(reweighter, Reweighter):
            w_train = reweighter.reweight(df_train).values
            w_valid = reweighter.reweight(df_valid).values
        else:
            raise ValueError("Unsupported reweighter type.")

View on GitHub (pinned to 79633dd950)

Solutions

  1. Verify dataset.segments contains both 'train' and 'valid' and each is non-empty: print(dataset.prepare('train').shape, dataset.prepare('valid').shape)
  2. Check the data handler's start_time/end_time overlap the loaded bin data (calendar range)
  3. Inspect processors in the handler config for dropna/filters that remove every row at learn time (DK_L)
  4. If no validation data is available, switch to LGBModel (gbdt.py) which treats 'valid' as optional

Example fix

# before
model = CatBoostModel()
model.fit(dataset)  # ValueError: Empty data from dataset

# after
# ensure segments cover real dates and yield rows
print({seg: dataset.prepare(seg, col_set=["feature","label"], data_key="learn").shape for seg in dataset.segments})
model.fit(dataset)
Defensive patterns

Strategy: validation

Validate before calling

df_train = dataset.prepare("train", col_set=["feature","label"], data_key="learn")
df_valid = dataset.prepare("valid", col_set=["feature","label"], data_key="learn")
assert not df_train.empty and not df_valid.empty, "train/valid segments are empty; check dataset config"

Try / catch

try:
    model.fit(dataset)
except ValueError as e:
    if "Empty data" in str(e):
        raise RuntimeError(f"Dataset segments empty: {dataset.segments}") from e
    raise

Prevention

When it happens

Trigger: Calling CatBoostModel.fit(dataset) where the DatasetH config lacks a 'valid' segment, has misaligned dates (train/valid ranges outside the calendar data), or where the learn-processing pipeline (data_key=DataHandlerLP.DK_L) drops all rows (e.g. dropna in process_type).

Common situations: Wrong handler start/end dates in the data handler config; segments defined over a date range with no traded instruments; a processor that filters out all samples; forgetting that CatBoost — unlike gbdt.py — makes the 'valid' segment mandatory.

Related errors


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