{"record":{"id":"786b3d2233621db9","repo":"hiyouga/LlamaFactory","slug":"dpo-training-dataset-is-empty-dataset-path","errorCode":null,"errorMessage":"DPO training dataset is empty: {dataset_path}","messagePattern":"DPO training dataset is empty: (.+?)","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"src/llamafactory/v1/trainers/dpo_trainer.py","lineNumber":73,"sourceCode":"        ref_rejected_logps: Log-probabilities from the reference model for rejected responses.\n        beta: Temperature / scaling factor for the DPO loss.\n        label_smoothing: Label smoothing factor in [0, 1].\n\n    Returns:\n        Per-sample element-wise loss tensor.\n    \"\"\"\n    chosen_logratios = policy_chosen_logps - ref_chosen_logps\n    rejected_logratios = policy_rejected_logps - ref_rejected_logps\n    logits = chosen_logratios - rejected_logratios\n    return -F.logsigmoid(beta * logits) * (1 - label_smoothing) - F.logsigmoid(-beta * logits) * label_smoothing\n\n\ndef _validate_dpo_dataset_format(train_dataset: DataEngine, dataset_path: str) -> None:\n    if train_dataset.streaming:\n        return\n\n    if len(train_dataset) == 0:\n        raise ValueError(f\"DPO training dataset is empty: {dataset_path}\")\n\n    sample = train_dataset[0]\n    if \"chosen_messages\" in sample and \"rejected_messages\" in sample:\n        return\n\n    dataset_name = sample.get(\"_dataset_name\", \"unknown\")\n    sample_keys = sorted(sample.keys())\n    raise ValueError(\n        \"DPO training requires pair-format samples containing chosen/rejected responses. \"\n        f\"First sample from dataset '{dataset_name}' has keys: {sample_keys}. \"\n        \"Please use pair data (e.g. a dataset with chosen_messages/rejected_messages).\"\n    )\n\n\nclass DPOTrainer(BaseTrainer):\n    def __init__(\n        self,\n        args: TrainingArguments,","sourceCodeStart":55,"sourceCodeEnd":91,"githubUrl":"https://github.com/hiyouga/LlamaFactory/blob/f28afaf6355af515454dfb16c97d728307c93897/src/llamafactory/v1/trainers/dpo_trainer.py#L55-L91","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Load the dataset manually (DataEngine or datasets.load_dataset) and print len() to confirm it is non-empty before constructing the trainer.","Check dataset_info.json entries, filtering options, and max_samples so samples are not all discarded.","If the dataset is genuinely streaming, ensure train_dataset.streaming is True so the check is bypassed.","Inspect the first raw row to verify the expected columns exist under the names the converter maps."],"exampleFix":null,"handlingStrategy":"validation","validationCode":"assert train_dataset.streaming or len(train_dataset) > 0, f\"dataset {dataset_path} is empty after preprocessing\"","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Log len(train_dataset) after preprocessing in every training script.","Dry-run the data pipeline on a small slice before a full launch."],"tags":["data","dataset","dpo","validation"],"backgroundTag":null,"analyzedSha":"f28afaf6355af515454dfb16c97d728307c93897","analyzedAt":"2026-08-14T21:57:28.298Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}