unslothai/unsloth · error · ValueError
dataset_slice_end must be greater than or equal to dataset_s
Error message
dataset_slice_end must be greater than or equal to dataset_slice_start
What it means
Raised by the _validate_dataset_slice model_validator on TrainingStartRequest. The optional dataset_slice_start/dataset_slice_end pair defines a row range of the dataset to train on; the validator enforces end >= start so the slice is never negative-length. start == end is deliberately allowed (a single-row slice) — the trainer warns but proceeds. The validator comment notes it is written to be order-independent relative to _check_steps_or_epochs.
Source
Thrown at studio/backend/models/training.py:219
values.setdefault("train_split", values.pop("split"))
return values
@field_validator("project_name")
@classmethod
def _normalize_project_name(cls, value: Optional[str]) -> Optional[str]:
return normalize_project_name(value)
# NOTE: pydantic runs all `mode="after"` validators in definition order, and
# `_check_steps_or_epochs` is lower in this class; keep these checks order-independent.
@model_validator(mode = "after")
def _validate_dataset_slice(self) -> "TrainingStartRequest":
# start == end is intentionally allowed (a deliberate single-row slice); the trainer warns.
if (
self.dataset_slice_start is not None
and self.dataset_slice_end is not None
and self.dataset_slice_end < self.dataset_slice_start
):
raise ValueError(
"dataset_slice_end must be greater than or equal to dataset_slice_start"
)
return self
@field_validator("hf_dataset")
@classmethod
def _check_hf_dataset(cls, v: Optional[str]) -> Optional[str]:
if v is None:
return v
v = v.strip()
if not v:
return None
if len(v) > 256:
raise ValueError("hf_dataset is too long (max 256 chars)")
if ".." in v:
raise ValueError("hf_dataset must not contain '..'")
if any(_HF_DATASET_ID_SEGMENT_RE.fullmatch(segment) is None for segment in v.split("/")):
raise ValueError("hf_dataset contains invalid characters or path segments")View on GitHub (pinned to 203007d190)
Solutions
- Make sure dataset_slice_end >= dataset_slice_start; for 'last N rows' semantics use start = total - N, end = total.
- Swap or clamp the pair client-side when the user inverts them.
- Remember start == end is valid (single-row slice) if that is the intent.
Example fix
// before
{ dataset_slice_start: 100, dataset_slice_end: 50 }
// after
{ dataset_slice_start: 50, dataset_slice_end: 100 } Defensive patterns
Strategy: validation
Validate before calling
def slice_ordered(body: dict) -> bool:
s, e = body.get("dataset_slice_start"), body.get("dataset_slice_end")
return s is None or e is None or e >= s Type guard
function sliceOrdered(s?: number | null, e?: number | null): boolean {
return s == null || e == null || e >= s;
} Prevention
- Use a range picker that enforces min<=max in the UI
- Compute end as start + length, never start - length
- Remember start == end is legal (single-row slice)
When it happens
Trigger: POST a training start request with e.g. dataset_slice_start=100 and dataset_slice_end=50, or defaults where start is user-supplied but end is a hard-coded smaller constant.
Common situations: UI two-number inputs where users can type start > end; paging logic that computes end as start - limit by an off-by-one; resuming a job with a stale slice_end from a shorter dataset; percentage-to-row conversions that produce inverted bounds.
Related errors
- hf_dataset is too long (max 256 chars)
- hf_dataset contains invalid characters or path segments
- subset is too long (max {MAX_HF_DATASET_OPTION_LENGTH} chars
- No captioned images found. Provide a metadata.jsonl / captio
- Unsupported local dataset format: {all_files[0]}
AI-assisted analysis of unslothai/unsloth@203007d190 (2026-08-15).
Data as JSON: /api/errors/ce2a8ecd879d83c7.
Report an issue: GitHub.