unslothai/unsloth · error · ValueError

scan_dataset requires a single Dataset split, not a DatasetD

Error message

scan_dataset requires a single Dataset split, not a DatasetDict. Available splits: {list(dataset.keys())}. Pass dataset[<split>] or use load_dataset(..., split='train').

What it means

ValueError from scan_dataset's input-type guard: the object passed is a DatasetDict or IterableDatasetDict (a mapping of splits), but the scanner needs one materialized Dataset because it iterates rows and reads column_names/len. The error message enumerates the available splits so the caller can immediately pick one.

Source

Thrown at studio/backend/utils/datasets/dataset_none_detect.py:519

    Raises ValueError if the format is unknown or unsupported.
    """
    # Reject a DatasetDict / IterableDatasetDict (load_dataset without split):
    # its column_names is a split map and would yield a confusing "unknown
    # format". Check both (IterableDatasetDict is not a DatasetDict subclass);
    # import locally so this module never hard-requires them.
    _dict_types = []
    try:
        from datasets import DatasetDict as _DatasetDict
        _dict_types.append(_DatasetDict)
    except ImportError:
        pass
    try:
        from datasets import IterableDatasetDict as _IterableDatasetDict
        _dict_types.append(_IterableDatasetDict)
    except ImportError:
        pass
    if _dict_types and isinstance(dataset, tuple(_dict_types)):
        raise ValueError(
            "scan_dataset requires a single Dataset split, not a DatasetDict. "
            f"Available splits: {list(dataset.keys())}. "
            "Pass dataset[<split>] or use load_dataset(..., split='train')."
        )
    # Streaming IterableDataset has no len()/column_names; give a clear error
    # instead of a confusing downstream TypeError.
    try:
        from datasets import IterableDataset as _IterableDataset
        if isinstance(dataset, _IterableDataset):
            raise ValueError(
                "scan_dataset requires a materialized Dataset, not an IterableDataset. "
                "Load without streaming=True, or materialize a slice first: "
                "Dataset.from_list(list(dataset.take(N)))."
            )
    except ImportError:
        pass
    fmt = FORMAT_ALIASES.get(fmt, fmt)
    was_auto = fmt == "auto"

View on GitHub (pinned to 203007d190)

Solutions

  1. Select a split: scan_dataset(dataset['train']) (use a split name from the error message)
  2. Load with a split from the start: load_dataset('repo', split='train')
  3. For multi-split audits, loop: for split in d.keys(): scan_dataset(d[split])

Example fix

# before
dataset = load_dataset('reddit_tifu')
stats = scan_dataset(dataset)  # DatasetDict -> raises

# after
dataset = load_dataset('reddit_tifu', split='train')
stats = scan_dataset(dataset)
Defensive patterns

Strategy: type-guard

Validate before calling

from datasets import Dataset, DatasetDict

def is_single_split(dataset) -> bool:
    return isinstance(dataset, Dataset)

Type guard

def is_single_split(dataset) -> bool:
    """True only for a materialized single-split Dataset."""
    from datasets import Dataset, DatasetDict, IterableDataset, IterableDatasetDict
    return isinstance(dataset, Dataset) and not isinstance(
        dataset, (DatasetDict, IterableDataset, IterableDatasetDict)
    )

Prevention

When it happens

Trigger: scan_dataset(load_dataset('repo')) — without split= the result is a DatasetDict; also passing dataset['train'] style access forgotten after refactoring, or handing an IterableDatasetDict from streaming loads.

Common situations: New users forgetting load_dataset(..., split='train'); datasets with only a 'test' or custom split name; helper code that accepted Dataset but now receives whatever load_dataset returns.

Related errors


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