{"record":{"id":"493157dcaed7ad84","repo":"Lightning-AI/pytorch-lightning","slug":"op-op-r-is-not-a-member-of-reduceop","errorCode":null,"errorMessage":"op {op!r} is not a member of `ReduceOp`","messagePattern":"op (.+?) is not a member of `ReduceOp`","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"src/lightning/fabric/plugins/collectives/torch_collective.py","lineNumber":218,"sourceCode":"        # 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":200,"sourceCodeEnd":220,"githubUrl":"https://github.com/Lightning-AI/pytorch-lightning/blob/9fed5c27d2a62ff0efd6c3573599921d6ff67c14/src/lightning/fabric/plugins/collectives/torch_collective.py#L200-L220","documentation":"After uppercasing a string `op`, `_convert_to_native_op` looks it up via `getattr(ReduceOp, op, None)`; if the name is not a member of `torch.distributed.ReduceOp` (e.g. 'avg' where unsupported, or a typo), this ValueError is raised.","triggerScenarios":"Passing a string like `op='product'`, `op='avg'` (not a member on some backends/torch versions), or a misspelling such as `op='suM'` that resolves to a nonexistent member, to all_reduce/reduce/reduce_scatter.","commonSituations":"Assuming all backends expose the same reduce-op names (NCCL vs Gloo differences across torch versions); copying op strings from other frameworks.","solutions":["Use the exact ReduceOp member name, e.g. `op='sum'`, `op='max'`, `op='min'`, `op='product'` — or better, pass `torch.distributed.ReduceOp.SUM` directly","Print/inspect valid members: `dir(torch.distributed.ReduceOp)`","Update the string for your torch version (member sets changed across releases)"],"exampleFix":"# before\ncollective.all_reduce(tensor, op='meansum')  # not a member\n\n# after\ncollective.all_reduce(tensor, op='sum')\n# or\nimport torch.distributed as dist\ncollective.all_reduce(tensor, op=dist.ReduceOp.SUM)","handlingStrategy":"validation","validationCode":"import torch.distributed as dist\nassert str(op).upper() in dir(dist.ReduceOp), f'{op!r} not a ReduceOp member'","typeGuard":"import torch.distributed as dist\ndef is_known_op(name: str) -> bool:\n    return getattr(dist.ReduceOp, name.upper(), None) is not None","tryCatchPattern":null,"preventionTips":["Prefer ReduceOp enum members over strings","Validate op names against dir(torch.distributed.ReduceOp) for your torch version"],"tags":["pytorch-lightning","distributed","reduceop","invalid-value"],"backgroundTag":"invalid-enum-value","analyzedSha":"9fed5c27d2a62ff0efd6c3573599921d6ff67c14","analyzedAt":"2026-08-28T11:52:41.083Z","schemaVersion":2},"datasetVersion":"2026-08-28T16:17:29.566Z"}