{"record":{"id":"311f578512cc299c","repo":"sgl-project/sglang","slug":"kv-gather-degree-does-not-compose-with-ulysses-deg","errorCode":null,"errorMessage":"kv_gather_degree does not compose with ulysses_degree or ring_degree yet; set exactly one of them above 1","messagePattern":"kv_gather_degree does not compose with ulysses_degree or ring_degree yet; set exactly one of them above 1","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"python/sglang/multimodal_gen/runtime/server_args/server_args.py","lineNumber":1365,"sourceCode":"                self.sp_split_auto = True\n                logger.info(\n                    \"Automatically set kv_gather_degree=sp_degree=2; set \"\n                    \"--ulysses-degree explicitly to keep the Ulysses exchange\"\n                )\n            else:\n                self.ulysses_degree = self.sp_degree\n                logger.info(\n                    \"Automatically set ulysses_degree=sp_degree=%d for the \"\n                    \"sequence-parallel process-group layout\",\n                    self.ulysses_degree,\n                )\n\n        if self.kv_gather_degree is None:\n            self.kv_gather_degree = 1\n\n        if self.kv_gather_degree > 1:\n            if (self.ulysses_degree or 1) != 1 or (self.ring_degree or 1) != 1:\n                raise ValueError(\n                    \"kv_gather_degree does not compose with ulysses_degree or \"\n                    \"ring_degree yet; set exactly one of them above 1\"\n                )\n\n        if self.ulysses_degree is None:\n            self.ulysses_degree = 1\n            logger.debug(\n                f\"Ulysses degree not set, using default value {self.ulysses_degree}\"\n            )\n\n        if self.ring_degree is None:\n            self.ring_degree = 1\n            logger.debug(f\"Ring degree not set, using default value {self.ring_degree}\")\n\n        if self.kv_gather_degree > 1:\n            # K/V-gather rows occupy the contiguous inner SP dimension; the\n            # process groups are built from ulysses_degree, so alias it until\n            # gather gets a first-class dimension (needed only once it","sourceCodeStart":1347,"sourceCodeEnd":1383,"githubUrl":"https://github.com/sgl-project/sglang/blob/0132848349585cfe6aae51c4941cbae872505f8a/python/sglang/multimodal_gen/runtime/server_args/server_args.py#L1347-L1383","documentation":"kv_gather_degree is a parallelism axis that is currently mutually exclusive with ulysses_degree and ring_degree. If kv_gather_degree > 1, both of the others must be 1 (or None, treated as 1).","triggerScenarios":"Setting --kv-gather-degree 2 together with --ulysses-degree 2 or --ring-degree > 1 in _adjust_parallelism.","commonSituations":"Migrating configs from a Ulysses/ring setup and adding kv_gather; enabling all parallelism knobs to maximize sharding; defaults changed so a previously-1 degree is now >1.","solutions":["Keep exactly one of kv_gather_degree / ulysses_degree / ring_degree above 1; set the others to 1","If Ulysses parallelism is required, unset --kv-gather-degree (leave it 1)","Recompute total parallelism against tp/ep world size after dropping one axis"],"exampleFix":"# before\n--kv-gather-degree 2 --ulysses-degree 2\n# after\n--ulysses-degree 2","handlingStrategy":"validation","validationCode":"axes = [kv_gather_degree or 1, ulysses_degree or 1, ring_degree or 1]\nassert sum(a > 1 for a in axes) <= 1, 'only one parallelism axis may exceed 1'","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Keep parallelism config in one place","Document the exclusivity in config templates"],"tags":["parallelism","config","validation"],"backgroundTag":"mutually-exclusive-options","analyzedSha":"0132848349585cfe6aae51c4941cbae872505f8a","analyzedAt":"2026-08-28T05:10:05.995Z","schemaVersion":2},"datasetVersion":"2026-08-28T06:17:29.519Z"}