{"record":{"id":"c895d11b077eb6d9","repo":"Lightning-AI/pytorch-lightning","slug":"unsupported-op-op-r-of-type-type-op-name","errorCode":null,"errorMessage":"Unsupported op {op!r} of type {type(op).__name__}","messagePattern":"Unsupported op (.+?) of type (.+?)","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"src/lightning/fabric/plugins/collectives/torch_collective.py","lineNumber":213,"sourceCode":"\n    @classmethod\n    @override\n    def destroy_group(cls, group: CollectibleGroup) -> None:\n        # can be called by all processes in the default group, group will be `object()` if they are not part of the\n        # current group\n        if group in dist.distributed_c10d._pg_map:\n            dist.destroy_process_group(group)\n\n    @classmethod\n    @override\n    def _convert_to_native_op(cls, op: Union[str, ReduceOp, RedOpType]) -> Union[ReduceOp, RedOpType]:\n        # `ReduceOp` is an empty shell for `RedOpType`, the latter being the actually returned class.\n        # For example, `ReduceOp.SUM` returns a `RedOpType.SUM`. the only exception is `RedOpType.PREMUL_SUM` where\n        # `ReduceOp` is still the desired class, but it's created via a special `_make_nccl_premul_sum` function\n        if isinstance(op, (ReduceOp, RedOpType)):\n            return op\n        if not isinstance(op, str):\n            raise ValueError(f\"Unsupported op {op!r} of type {type(op).__name__}\")\n        op = op.upper()\n        # `ReduceOp` should contain `RedOpType`'s members\n        value = getattr(ReduceOp, op, None)\n        if value is None:\n            raise ValueError(f\"op {op!r} is not a member of `ReduceOp`\")\n        return value\n","sourceCodeStart":195,"sourceCodeEnd":220,"githubUrl":"https://github.com/Lightning-AI/pytorch-lightning/blob/9fed5c27d2a62ff0efd6c3573599921d6ff67c14/src/lightning/fabric/plugins/collectives/torch_collective.py#L195-L220","documentation":"`_convert_to_native_op` converts the `op` argument of all_reduce/reduce/reduce_scatter into a native `ReduceOp`/`RedOpType`. If `op` is neither a ReduceOp/RedOpType instance nor a string, it raises this ValueError — only those two types are accepted.","triggerScenarios":"Passing an int raw op code, None, a custom enum, or an object as `op=` to `collective.all_reduce(tensor, op=...)`, `reduce`, or `reduce_scatter`.","commonSituations":"Porting code that used raw integer op codes from older torch.distributed APIs; passing `dist.ReduceOp.SUM` from a mismatched torch namespace or a different library's enum; typos causing unexpected object types.","solutions":["Pass a `torch.distributed.ReduceOp` member directly, e.g. `op=torch.distributed.ReduceOp.SUM`","Or pass its name as a string: `op='sum'` / `op='MAX'` (it is uppercased and looked up on ReduceOp)","Remove custom int/op-code values; there is no mapping from raw ints in this API"],"exampleFix":"# before\ncollective.all_reduce(tensor, op=2)  # int not supported\n\n# after\nimport torch.distributed as dist\ncollective.all_reduce(tensor, op=dist.ReduceOp.SUM)\n# or: collective.all_reduce(tensor, op='sum')","handlingStrategy":"type-guard","validationCode":"import torch.distributed as dist\nassert isinstance(op, (str, dist.ReduceOp)), 'op must be str or ReduceOp'","typeGuard":"import torch.distributed as dist\ndef is_valid_op(op) -> bool:\n    return isinstance(op, str) or isinstance(op, (dist.ReduceOp, dist.ReduceOp.RedOpType))","tryCatchPattern":null,"preventionTips":["Pass torch.distributed.ReduceOp members, not int op codes","Centralize op constants in one module"],"tags":["pytorch-lightning","distributed","reduceop","type-validation"],"backgroundTag":"invalid-enum-argument","analyzedSha":"9fed5c27d2a62ff0efd6c3573599921d6ff67c14","analyzedAt":"2026-08-28T11:52:41.083Z","schemaVersion":2},"datasetVersion":"2026-08-28T16:17:29.566Z"}