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

  1. Make sure dataset_slice_end >= dataset_slice_start; for 'last N rows' semantics use start = total - N, end = total.
  2. Swap or clamp the pair client-side when the user inverts them.
  3. 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

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


AI-assisted analysis of unslothai/unsloth@203007d190 (2026-08-15). Data as JSON: /api/errors/ce2a8ecd879d83c7. Report an issue: GitHub.