{"record":{"id":"8ce9b4cdaf700441","repo":"vllm-project/vllm","slug":"tp-size-tp-must-be-divisible-by-dcp-size-dcp","errorCode":null,"errorMessage":"tp_size={tp} must be divisible by dcp_size={dcp}.","messagePattern":"tp_size=(.+?) must be divisible by dcp_size=(.+?)\\.","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"vllm/config/parallel.py","lineNumber":532,"sourceCode":"                )\n        else:\n            if self.eplb_config.num_redundant_experts != 0:\n                raise ValueError(\n                    \"num_redundant_experts is set to \"\n                    f\"{self.eplb_config.num_redundant_experts} but EPLB is not \"\n                    \"enabled. Either enable EPLB or unset \"\n                    \"num_redundant_experts.\"\n                )\n\n        tp = self.tensor_parallel_size\n        pcp = self.prefill_context_parallel_size\n        dcp = self.decode_context_parallel_size\n        if pcp > 1 and self.data_parallel_size > 1:\n            raise ValueError(\"PCP does not support data parallelism yet.\")\n        if pcp == 1:\n            # DCP reuses the TP ranks when PCP is disabled.\n            if tp % dcp != 0:\n                raise ValueError(f\"tp_size={tp} must be divisible by dcp_size={dcp}.\")\n        elif dcp not in (1, pcp, tp * pcp):\n            raise ValueError(\n                \"When PCP is enabled, DCP must be disabled, span the PCP \"\n                \"axis, or span the full TP x PCP axis. \"\n                f\"Got TP={tp}, PCP={pcp}, DCP={dcp}; valid DCP sizes are \"\n                f\"{sorted({1, pcp, tp * pcp})}.\"\n            )\n\n        if self.dcp_comm_backend == \"a2a\" and self.decode_context_parallel_size <= 1:\n            raise ValueError(\n                \"dcp_comm_backend='a2a' requires decode_context_parallel_size > 1.\"\n            )\n\n        return self\n\n    @property\n    def world_size_across_dp(self) -> int:\n        \"\"\"Process world size across TP, PCP, PP, and DP.\"\"\"","sourceCodeStart":514,"sourceCodeEnd":550,"githubUrl":"https://github.com/vllm-project/vllm/blob/c794754062d49a8fdb63ab3c5215b488b865030c/vllm/config/parallel.py#L514-L550","documentation":"When PCP is disabled, decode context parallelism (DCP) reuses the tensor-parallel ranks, so the TP size must be divisible by the DCP size. ParallelConfig raises tp % dcp != 0 in this branch.","triggerScenarios":"Config with prefill_context_parallel_size=1 and a decode_context_parallel_size that does not divide tensor_parallel_size, e.g. TP=4 with DCP=3, or TP=2 with DCP=4.","commonSituations":"Hand-tuning DCP for long-context decode without checking rank factorization; changing TP size after DCP was already set.","solutions":["Pick a DCP size that divides TP, e.g. TP=4 supports DCP in {1, 2, 4}.","Or raise TP to a multiple of the desired DCP size.","Set DCP back to 1 if decode context parallelism is not needed."],"exampleFix":"# before\n--tensor-parallel-size 4 --decode-context-parallel-size 3\n# after\n--tensor-parallel-size 4 --decode-context-parallel-size 2","handlingStrategy":"validation","validationCode":"def tp_dcp_valid(tp: int, dcp: int, pcp: int = 1) -> bool:\n    return pcp > 1 or tp % dcp == 0\n\nassert tp_dcp_valid(4, 2)","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Compute DCP as a divisor of TP (tp // k) in launch scripts instead of a hardcoded constant.","When changing TP, re-derive every dependent parallel size in the same change."],"tags":["context-parallelism","tensor-parallel","parallelism","configuration"],"backgroundTag":null,"analyzedSha":"c794754062d49a8fdb63ab3c5215b488b865030c","analyzedAt":"2026-08-14T21:17:39.825Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}