hiyouga/LlamaFactory · error · ValueError

DPO training dataset is empty: {dataset_path}

Error message

DPO training dataset is empty: {dataset_path}

What it means

ValueError from _validate_dpo_dataset_format (dpo_trainer.py:73) when the non-streaming train DataEngine has zero samples. It is an early, explicit check so the user sees a clear message at trainer construction instead of a confusing empty-dataloader failure mid-run. Streaming datasets are exempted because their length cannot be known up front.

Source

Thrown at src/llamafactory/v1/trainers/dpo_trainer.py:73

        ref_rejected_logps: Log-probabilities from the reference model for rejected responses.
        beta: Temperature / scaling factor for the DPO loss.
        label_smoothing: Label smoothing factor in [0, 1].

    Returns:
        Per-sample element-wise loss tensor.
    """
    chosen_logratios = policy_chosen_logps - ref_chosen_logps
    rejected_logratios = policy_rejected_logps - ref_rejected_logps
    logits = chosen_logratios - rejected_logratios
    return -F.logsigmoid(beta * logits) * (1 - label_smoothing) - F.logsigmoid(-beta * logits) * label_smoothing


def _validate_dpo_dataset_format(train_dataset: DataEngine, dataset_path: str) -> None:
    if train_dataset.streaming:
        return

    if len(train_dataset) == 0:
        raise ValueError(f"DPO training dataset is empty: {dataset_path}")

    sample = train_dataset[0]
    if "chosen_messages" in sample and "rejected_messages" in sample:
        return

    dataset_name = sample.get("_dataset_name", "unknown")
    sample_keys = sorted(sample.keys())
    raise ValueError(
        "DPO training requires pair-format samples containing chosen/rejected responses. "
        f"First sample from dataset '{dataset_name}' has keys: {sample_keys}. "
        "Please use pair data (e.g. a dataset with chosen_messages/rejected_messages)."
    )


class DPOTrainer(BaseTrainer):
    def __init__(
        self,
        args: TrainingArguments,

View on GitHub (pinned to f28afaf635)

Solutions

  1. Load the dataset manually (DataEngine or datasets.load_dataset) and print len() to confirm it is non-empty before constructing the trainer.
  2. Check dataset_info.json entries, filtering options, and max_samples so samples are not all discarded.
  3. If the dataset is genuinely streaming, ensure train_dataset.streaming is True so the check is bypassed.
  4. Inspect the first raw row to verify the expected columns exist under the names the converter maps.
Defensive patterns

Strategy: validation

Validate before calling

assert train_dataset.streaming or len(train_dataset) > 0, f"dataset {dataset_path} is empty after preprocessing"

Prevention

When it happens

Trigger: Calling DPOTrainer with a DataEngine whose filtered/processed dataset has 0 rows: empty dataset file, all samples filtered out by a max-samples or filter setting, or a dataset_info entry pointing at a file with no records.

Common situations: max_samples smaller than the skip offset; a converter/template dropping every sample; wrong dataset name in dataset_info.json resolving to an empty file; train/prompt column names not matching so 0 rows survive preprocessing.

Related errors


AI-assisted analysis of hiyouga/LlamaFactory@f28afaf635 (2026-08-14). Data as JSON: /api/errors/786b3d2233621db9. Report an issue: GitHub.