{"record":{"id":"600f2f81a9e30c16","repo":"vllm-project/vllm","slug":"unsupported-op-op","errorCode":null,"errorMessage":"Unsupported op: {op}","messagePattern":"Unsupported op: (.+?)","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"vllm/distributed/device_communicators/pynccl_wrapper.py","lineNumber":157,"sourceCode":"    ncclProd = 1\n    ncclMax = 2\n    ncclMin = 3\n    ncclAvg = 4\n    ncclNumOps = 5\n\n    @classmethod\n    def from_torch(cls, op: ReduceOp) -> int:\n        if op == ReduceOp.SUM:\n            return cls.ncclSum\n        if op == ReduceOp.PRODUCT:\n            return cls.ncclProd\n        if op == ReduceOp.MAX:\n            return cls.ncclMax\n        if op == ReduceOp.MIN:\n            return cls.ncclMin\n        if op == ReduceOp.AVG:\n            return cls.ncclAvg\n        raise ValueError(f\"Unsupported op: {op}\")\n\n\n@dataclass\nclass Function:\n    name: str\n    restype: Any\n    argtypes: list[Any]\n\n\nclass NCCLLibrary:\n    exported_functions = [\n        # const char* ncclGetErrorString(ncclResult_t result)\n        Function(\"ncclGetErrorString\", ctypes.c_char_p, [ncclResult_t]),\n        # ncclResult_t  ncclGetVersion(int *version);\n        Function(\"ncclGetVersion\", ncclResult_t, [ctypes.POINTER(ctypes.c_int)]),\n        # ncclResult_t ncclGetUniqueId(ncclUniqueId* uniqueId);\n        Function(\"ncclGetUniqueId\", ncclResult_t, [ctypes.POINTER(ncclUniqueId)]),\n        # ncclResult_t  ncclCommInitRank(","sourceCodeStart":139,"sourceCodeEnd":175,"githubUrl":"https://github.com/vllm-project/vllm/blob/c794754062d49a8fdb63ab3c5215b488b865030c/vllm/distributed/device_communicators/pynccl_wrapper.py#L139-L175","documentation":"ncclRedOpTypeEnum.from_torch translates a torch.distributed.ReduceOp into an NCCL reduction operator. Only SUM, PRODUCT, MAX, MIN and AVG are mapped; NCCL has no enum for bitwise or other torch ops, so anything else raises ValueError('Unsupported op: {op}').","triggerScenarios":"Calling a PyNccl-backed collective with op=ReduceOp.BAND / BOR / BXOR (no NCCL equivalent), or passing the ReduceOp handle itself instead of a member (op=ReduceOp instead of ReduceOp.SUM).","commonSituations":"Porting torch.distributed code that used bitwise reduce ops for mask/flag tensors; passing a default ReduceOp object from a generic wrapper that assumed a different enum surface.","solutions":["Use one of ReduceOp.SUM, PRODUCT, MAX, MIN or AVG for collectives routed through PyNccl","For bitwise data, pack bits into int32 and use MAX/SUM semantics that reproduce the intended result","Route bitwise collectives through torch.distributed (gloo/nccl process group) instead of the pynccl wrapper"],"exampleFix":"# before\npynccl.all_reduce(x, op=ReduceOp.BOR)  # ValueError\n\n# after\n# bitwise-or of 0/1 flags == max\npynccl.all_reduce(x, op=ReduceOp.MAX)","handlingStrategy":"type-guard","validationCode":"SUPPORTED_OPS = {ReduceOp.SUM, ReduceOp.PRODUCT, ReduceOp.MAX, ReduceOp.MIN, ReduceOp.AVG}\nassert op in SUPPORTED_OPS, f\"{op} has no NCCL equivalent; pick SUM/PRODUCT/MAX/MIN/AVG\"","typeGuard":"def nccl_op_supported(op: ReduceOp) -> bool:\n    return op in {ReduceOp.SUM, ReduceOp.PRODUCT, ReduceOp.MAX, ReduceOp.MIN, ReduceOp.AVG}","tryCatchPattern":"try:\n    ncclRedOpTypeEnum.from_torch(op)\nexcept ValueError:\n    op = ReduceOp.SUM  # choose a semantically valid fallback","preventionTips":["Avoid bitwise ReduceOps on pynccl paths","Wrap op selection behind a whitelist helper","Unit-test collective helpers against all ReduceOp members"],"tags":["nccl","reduce-op","distributed","validation"],"backgroundTag":null,"analyzedSha":"c794754062d49a8fdb63ab3c5215b488b865030c","analyzedAt":"2026-08-14T21:17:39.825Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}