{"record":{"id":"b1842e24dc003963","repo":"open-mmlab/mmdetection","slug":"output-of-cast-data-should-be-a-dict-or-a-tuple","errorCode":null,"errorMessage":"Output of `cast_data` should be a dict or a tuple with inputs and data_samples, but got{type(data)}: {data}","messagePattern":"Output of `cast_data` should be a dict or a tuple with inputs and data_samples, but got(.+?): (.+?)","errorType":"exception","errorClass":"TypeError","httpStatus":null,"severity":"error","filePath":"mmdet/models/data_preprocessors/data_preprocessor.py","lineNumber":180,"sourceCode":"                pad_w = int(\n                    np.ceil(ori_input.shape[2] /\n                            self.pad_size_divisor)) * self.pad_size_divisor\n                batch_pad_shape.append((pad_h, pad_w))\n        # Process data with `default_collate`.\n        elif isinstance(_batch_inputs, torch.Tensor):\n            assert _batch_inputs.dim() == 4, (\n                'The input of `ImgDataPreprocessor` should be a NCHW tensor '\n                'or a list of tensor, but got a tensor with shape: '\n                f'{_batch_inputs.shape}')\n            pad_h = int(\n                np.ceil(_batch_inputs.shape[2] /\n                        self.pad_size_divisor)) * self.pad_size_divisor\n            pad_w = int(\n                np.ceil(_batch_inputs.shape[3] /\n                        self.pad_size_divisor)) * self.pad_size_divisor\n            batch_pad_shape = [(pad_h, pad_w)] * _batch_inputs.shape[0]\n        else:\n            raise TypeError('Output of `cast_data` should be a dict '\n                            'or a tuple with inputs and data_samples, but got'\n                            f'{type(data)}: {data}')\n        return batch_pad_shape\n\n    def pad_gt_masks(self,\n                     batch_data_samples: Sequence[DetDataSample]) -> None:\n        \"\"\"Pad gt_masks to shape of batch_input_shape.\"\"\"\n        if 'masks' in batch_data_samples[0].gt_instances:\n            for data_samples in batch_data_samples:\n                masks = data_samples.gt_instances.masks\n                data_samples.gt_instances.masks = masks.pad(\n                    data_samples.batch_input_shape,\n                    pad_val=self.mask_pad_value)\n\n    def pad_gt_sem_seg(self,\n                       batch_data_samples: Sequence[DetDataSample]) -> None:\n        \"\"\"Pad gt_sem_seg to shape of batch_input_shape.\"\"\"\n        if 'gt_sem_seg' in batch_data_samples[0]:","sourceCodeStart":162,"sourceCodeEnd":198,"githubUrl":"https://github.com/open-mmlab/mmdetection/blob/cfd5d3a985b0249de009b67d04f37263e11cdf3d/mmdet/models/data_preprocessors/data_preprocessor.py#L162-L198","documentation":"DetDataPreprocessor._get_pad_shape expects data produced by cast_data to be either a dict (with 'inputs') or a tuple/list of (inputs, data_samples). Any other structure raises TypeError because the pad shape cannot be derived.","triggerScenarios":"Calling data_preprocessor.forward(data) with a raw list of tensors, a single Tensor, or a custom collate output that is not a dict/tuple; test_step/forward with a non-standard data structure.","commonSituations":"Custom dataloaders whose collate_fn returns lists of samples instead of the mmdet structure; wrapping the preprocessor with third-party code that reshapes batches; feeding non-collated data during debugging.","solutions":["Ensure data comes from the mmdet dataloader/collate_data (dict with 'inputs' and 'data_samples')","If building batches manually, use the structure {'inputs': Tensor, 'data_samples': list[DetDataSample]}","Call cast_data (usually done in forward) before _get_pad_shape via test_pad_shape/forward"],"exampleFix":"// before\ndata = [img_tensor1, img_tensor2]  # raw list\nout = preprocessor(data)\n// after\nfrom mmdet.structures import DetDataSample\ndata = dict(inputs=torch.stack([img1, img2]), data_samples=[DetDataSample(), DetDataSample()])\nout = preprocessor(data, training=False)","handlingStrategy":"type-guard","validationCode":"assert isinstance(data, dict) and 'inputs' in data or (isinstance(data, (tuple, list)) and len(data) == 2)","typeGuard":"def is_valid_batch(data) -> bool:\\n    return (isinstance(data, dict) and 'inputs' in data) or (isinstance(data, (tuple, list)) and len(data) == 2)","tryCatchPattern":"try:\\n    out = preprocessor(data, training=False)\\nexcept TypeError as e:\\n    raise ValueError(f'Bad batch structure for preprocessor: {type(data)}') from e","preventionTips":["Always feed data from mmdet dataloaders","Use dict(inputs=..., data_samples=...) when building batches manually"],"tags":["mmdet","data-preprocessor","batch-structure","type-error"],"backgroundTag":"unexpected-input-shape","analyzedSha":"cfd5d3a985b0249de009b67d04f37263e11cdf3d","analyzedAt":"2026-08-27T20:54:20.183Z","schemaVersion":2},"datasetVersion":"2026-08-28T00:17:15.603Z"}