{"record":{"id":"51d5da3c22460d56","repo":"hiyouga/LlamaFactory","slug":"streaming-dataset-does-not-support-index-access","errorCode":null,"errorMessage":"Streaming dataset does not support index access.","messagePattern":"Streaming dataset does not support index access\\.","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"src/llamafactory/v1/core/data_engine.py","lineNumber":182,"sourceCode":"        Returns:\n            int: Dataset length.\n        \"\"\"\n        if self.streaming:\n            return -1\n        else:\n            return len(self.data_index)\n\n    def __getitem__(self, index: int | Any) -> Sample | list[Sample]:\n        \"\"\"Get dataset item.\n\n        Args:\n            index (int): Dataset index.\n\n        Returns:\n            Sample: Dataset item.\n        \"\"\"\n        if self.streaming:\n            raise ValueError(\"Streaming dataset does not support index access.\")\n\n        if isinstance(index, int):\n            return self._get(*self.data_index[index])\n        else:  # data selector plugin\n            from ..plugins.data_plugins.loader import select_data_sample\n\n            selected_index = select_data_sample(self.data_index, index)\n            if isinstance(selected_index, list):\n                return [self._get(*entry) for entry in selected_index]\n            else:\n                return self._get(*selected_index)\n\n    def _get(self, dataset_name: str, sample_index: int, cut: int | None = None) -> Sample:\n        \"\"\"Convert one raw row, truncating to a multi-turn prefix when ``cut`` is set.\"\"\"\n        sample = self._convert_data_sample(self.datasets[dataset_name][sample_index], dataset_name)\n        if cut is not None and \"messages\" in sample:\n            sample = {**sample, \"messages\": sample[\"messages\"][:cut]}\n        return sample","sourceCodeStart":164,"sourceCodeEnd":200,"githubUrl":"https://github.com/hiyouga/LlamaFactory/blob/f28afaf6355af515454dfb16c97d728307c93897/src/llamafactory/v1/core/data_engine.py#L164-L200","documentation":"The v1 `DataEngine.__getitem__` raises immediately when `self.streaming` is true, because index-based random access requires a materialized `data_index`, and streaming `IterableDataset`s only support sequential iteration. This blocks DataLoader workers and any selection plugin that assumes positional indexing.","triggerScenarios":"Any code path that calls `dataset[i]` (dataloader with a sampler, a `select(...)` data-selector plugin, or manual probing) while the DataEngine was constructed with one or more streaming datasets.","commonSituations":"Enabling `streaming: true` for a huge hub dataset but keeping a training loop or evaluation code that samples by index; using shuffling/eval splits that require `len()` and random access.","solutions":["Remove `streaming: true` so the dataset is materialized and indexable (ensure disk for the download)","Keep streaming and iterate sequentially instead of indexing (e.g. iterate the engine's stream, use `.take()/.skip()` style ops on the IterableDataset)","For evaluation on a subset, materialize only the eval split locally and stream only the train split in a separate engine"],"exampleFix":"# before\nfor i in range(len(dataset)):   # or dataset[0]\n    sample = dataset[i]          # ValueError: streaming\n\n# after (non-streaming)\ndataset_info:\n  mydata:\n    path: org/data\n    # streaming: true  <- removed\nsample = dataset[0]","handlingStrategy":"type-guard","validationCode":"def assert_indexable(engine) -> None:\n    if getattr(engine, \"streaming\", False):\n        raise SystemExit(\"engine is streaming; index access unsupported — materialize the dataset first\")","typeGuard":"from llamafactory.v1.core.data_engine import DataEngine\n\ndef is_indexable(engine: DataEngine) -> bool:\n    return not getattr(engine, \"streaming\", False)","tryCatchPattern":"try:\n    sample = engine[i]\nexcept ValueError as e:\n    if \"Streaming dataset\" in str(e):\n        # fall back to sequential iteration for streaming engines\n        it = iter(engine)  # or engine.iterate()\n    else:\n        raise","preventionTips":["Branch training code on `engine.streaming` before any indexing","Use sequential iteration or IterableDataset ops (take/skip/shuffle(buffer)) for streams","Materialize eval splits locally so evaluation keeps random access"],"tags":["v1","datasets","streaming","api-misuse"],"backgroundTag":null,"analyzedSha":"f28afaf6355af515454dfb16c97d728307c93897","analyzedAt":"2026-08-14T21:57:28.298Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}