hiyouga/LlamaFactory · error · ValueError
Drop last must be True.
Error message
Drop last must be True.
What it means
The v1 batching scheduler is built around StatefulDistributedSampler with drop_last semantics: every batch must be exactly global_batch_size so checkpoint-resumable step accounting stays exact. drop_last=False would produce a ragged final batch and break stateful resume, so it is rejected outright rather than silently supported.
Source
Thrown at src/llamafactory/v1/core/utils/batching.py:198
self.drop_last = drop_last
self.seed = seed
self._warned_truncation = False # warn once when dropping fully-truncated (zero-loss) samples
# TODO: support length and infinity
dp_size = DistributedInterface().get_world_size(Dim.DP)
if self.global_batch_size is None:
self.global_batch_size = dp_size * micro_batch_size
self.num_micro_batch = 1
elif self.global_batch_size % (dp_size * micro_batch_size) == 0:
self.num_micro_batch = global_batch_size // dp_size // micro_batch_size
else:
raise ValueError(
"Global batch size must be divisible by DP size and micro batch size. "
f"Got {global_batch_size} % ({dp_size} * {micro_batch_size}) != 0."
)
if not self.drop_last:
raise ValueError("Drop last must be True.")
self._batch_info: BatchInfo = {
"micro_batch_size": self.micro_batch_size,
"num_micro_batch": self.num_micro_batch,
"cutoff_len": self.cutoff_len,
}
self._init_data_provider()
self._is_resuming: bool = False
self._data_iter = iter(self._data_provider)
self._buffer = StatefulBuffer()
logger.info_rank0(
f"Init unified data loader with global batch size {self.global_batch_size}, "
f"micro batch size {self.micro_batch_size}, "
f"num micro batch {self.num_micro_batch}, "
f"cutoff len {self.cutoff_len}, "View on GitHub (pinned to f28afaf635)
Solutions
- Pass drop_last=True (the only supported mode in v1)
- If losing tail samples matters, oversize/repeat the dataset or accept the drop — v1's stateful resume requires uniform batches
- Stay on the v0 pipeline if you need partial final batches
Example fix
# before sched = Batching(global_batch_size=128, micro_batch_size=32, drop_last=False) # after sched = Batching(global_batch_size=128, micro_batch_size=32, drop_last=True)
Defensive patterns
Strategy: validation
Validate before calling
assert drop_last is True, "v1 batching requires drop_last=True"
Prevention
- Treat drop_last=True as fixed in v1 config templates
- Do not port v0 DataLoader flags verbatim into v1 batching arguments
When it happens
Trigger: Instantiating the v1 batching/scheduler class with drop_last=False. There is no code path that tolerates it — the check is immediate.
Common situations: Reusing a v0 DataLoader habit (v0 commonly runs drop_last=False) in v1 configs; wrapping the scheduler with a generic loader factory that defaults drop_last=False.
Related errors
- Global batch size must be divisible by DP size and micro bat
- Unsupported model type: {getattr(config, 'model_type')}.
- Template is required for MultiModalDataCollator.
- Cannot specify `val_size` if `eval_dataset` is not None.
- batching_strategy={self.batching_strategy.value!r} does not
AI-assisted analysis of hiyouga/LlamaFactory@f28afaf635 (2026-08-14).
Data as JSON: /api/errors/ccb57e1148152960.
Report an issue: GitHub.