{"record":{"id":"58f82bb0b8782b83","repo":"Lightning-AI/pytorch-lightning","slug":"the-dataloader-dataloader-needs-to-subclass-tor","errorCode":null,"errorMessage":"The dataloader {dataloader} needs to subclass `torch.utils.data.DataLoader`","messagePattern":"The dataloader (.+?) needs to subclass `torch\\.utils\\.data\\.DataLoader`","errorType":"exception","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"src/lightning/fabric/utilities/data.py","lineNumber":85,"sourceCode":"            \"Your `IterableDataset` has `__len__` defined.\"\n            \" In combination with multi-process data loading (when num_workers > 1),\"\n            \" `__len__` could be inaccurate if each worker is not configured independently\"\n            \" to avoid having duplicate data.\"\n        )\n    return length is not None\n\n\ndef _update_dataloader(dataloader: DataLoader, sampler: Union[Sampler, Iterable]) -> DataLoader:\n    dl_args, dl_kwargs = _get_dataloader_init_args_and_kwargs(dataloader, sampler)\n    return _reinstantiate_wrapped_cls(dataloader, *dl_args, **dl_kwargs)\n\n\ndef _get_dataloader_init_args_and_kwargs(\n    dataloader: DataLoader,\n    sampler: Union[Sampler, Iterable],\n) -> tuple[tuple[Any], dict[str, Any]]:\n    if not isinstance(dataloader, DataLoader):\n        raise ValueError(f\"The dataloader {dataloader} needs to subclass `torch.utils.data.DataLoader`\")\n\n    was_wrapped = hasattr(dataloader, \"__pl_saved_args\")\n    if was_wrapped:\n        dl_args = dataloader.__pl_saved_args\n        dl_kwargs = dataloader.__pl_saved_kwargs\n        arg_names = dataloader.__pl_saved_arg_names\n        original_dataset = dataloader.__dataset  # we have this saved from _wrap_init\n    else:\n        # get the dataloader instance attributes\n        attrs = {k: v for k, v in vars(dataloader).items() if not k.startswith(\"_\")}\n        # We cannot be 100% sure the class sets dataset argument. Let's set it to None to be safe\n        # and hope we can get it from the instance attributes\n        original_dataset = None\n        # not part of `vars`\n        attrs[\"multiprocessing_context\"] = dataloader.multiprocessing_context\n        arg_names = ()\n\n    # get the dataloader instance `__init__` parameters","sourceCodeStart":67,"sourceCodeEnd":103,"githubUrl":"https://github.com/Lightning-AI/pytorch-lightning/blob/9fed5c27d2a62ff0efd6c3573599921d6ff67c14/src/lightning/fabric/utilities/data.py#L67-L103","documentation":"Lightning's _update_dataloader/_get_dataloader_init_args_and_kwargs rebuilds a dataloader with a new distributed sampler by re-playing its __init__ arguments, which requires the object to be an instance of torch.utils.data.DataLoader. Custom or third-party dataloader classes that don't subclass DataLoader (e.g. some graph/point-cloud libraries, HF-specific iterables) cannot be re-constructed this way.","triggerScenarios":"Passing a non-DataLoader iterable (custom loader class, library-specific loader like some PyG variants) into a distributed Fabric/Lightning setup where Lightning calls _update_dataloader to inject a DistributedSampler; e.g. fabric.setup_dataloaders(loader).","commonSituations":"Wrapping exotic loader classes from domain libraries; passing DataChunk/Iterable wrappers; versions of libraries that changed loader base classes.","solutions":["Subclass torch.utils.data.DataLoader in your custom loader so Lightning can replay its init args","Wrap your dataset/batch iterator in a standard torch DataLoader instead of a bespoke loader class","If the object only supports iteration, provide the sampler logic yourself and avoid paths that require re-wrapping (e.g. don't pass it through fabric.setup_dataloaders)"],"exampleFix":"# before\nclass MyLoader:  # not a DataLoader\n    def __init__(self, data): ...\n\n# after\nfrom torch.utils.data import DataLoader\nclass MyLoader(DataLoader):\n    def __init__(self, data, **kwargs):\n        super().__init__(dataset=MyDataset(data), **kwargs)","handlingStrategy":"type-guard","validationCode":"from torch.utils.data import DataLoader\nassert isinstance(loader, DataLoader), 'pass a torch.utils.data.DataLoader subclass to setup_dataloaders'","typeGuard":"from torch.utils.data import DataLoader\n\ndef is_torch_dataloader(obj) -> bool:\n    return isinstance(obj, DataLoader)","tryCatchPattern":null,"preventionTips":["Standardize on torch DataLoader subclasses for anything passed to distributed setup","Wrap custom iterables in a dataset + standard DataLoader"],"tags":["dataloader","distributed","sampler","type-error","lightning-fabric"],"backgroundTag":"invalid-argument-type","analyzedSha":"9fed5c27d2a62ff0efd6c3573599921d6ff67c14","analyzedAt":"2026-08-28T11:52:41.083Z","schemaVersion":2},"datasetVersion":"2026-08-28T16:17:29.566Z"}