{"record":{"id":"fe73b9950f91e16e","repo":"sgl-project/sglang","slug":"encoder-dp-mode-requires-dp-size-1-and-tp-si","errorCode":null,"errorMessage":"Encoder DP mode requires --dp-size > 1 and --tp-size 1; got dp_size={get_parallel().dp_size}, tp_size={get_parallel().tp_size}.","messagePattern":"Encoder DP mode requires --dp-size > 1 and --tp-size 1; got dp_size=(.+?), tp_size=(.+?)\\.","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"critical","filePath":"python/sglang/srt/disaggregation/encoder/runtime.py","lineNumber":1574,"sourceCode":"        coalesce_same_turn=coalesce_same_turn,\n    )\n    return EncoderRuntime(\n        encoder=encoder,\n        scheduler=scheduler,\n        send_sockets=send_sockets,\n        zmq_context=zmq_context,\n        tp_processes=tp_processes,\n    )\n\n\ndef launch_dp_runtime(server_args: ServerArgs) -> DPDispatcher:\n    \"\"\"Launch the protocol-neutral DP backend and return its dispatcher.\n\n    HTTP uses this entry point today.  gRPC can reuse it later without\n    importing HTTP application state or Uvicorn.\n    \"\"\"\n    if get_parallel().dp_size <= 1 or get_parallel().tp_size != 1:\n        raise ValueError(\n            \"Encoder DP mode requires --dp-size > 1 and --tp-size 1; got \"\n            f\"dp_size={get_parallel().dp_size}, tp_size={get_parallel().tp_size}.\"\n        )\n    dp_size = get_parallel().dp_size\n    logger.info(f\"Launching encoder in DP mode: dp_size={dp_size}\")\n\n    # DP mode: workers (subprocesses) write metrics to the shared multiproc dir;\n    # the main process exposes the aggregated /metrics endpoint.\n    if get_observability().enable_metrics:\n        set_prometheus_multiproc_dir()\n\n    ctx = mp.get_context(\"spawn\")\n    ipc_prefix = random_uuid()\n    async_zmq_ctx = zmq.asyncio.Context(dp_size + 1)\n\n    result_path = f\"ipc:///tmp/{ipc_prefix}_dp_result\"\n    result_socket = get_zmq_socket(async_zmq_ctx, zmq.PULL, result_path, True)\n    dispatch_sockets: List[zmq.asyncio.Socket] = [","sourceCodeStart":1556,"sourceCodeEnd":1592,"githubUrl":"https://github.com/sgl-project/sglang/blob/0132848349585cfe6aae51c4941cbae872505f8a/python/sglang/srt/disaggregation/encoder/runtime.py#L1556-L1592","documentation":"launch_dp_runtime builds the DP-mode encoder backend and enforces its contract: DP mode needs more than one data-parallel rank (--dp-size > 1) and exactly one tensor-parallel rank (--tp-size 1). Violating either raises ValueError at startup.","triggerScenarios":"Launching the DP encoder runtime with --dp-size 1 (which is the local runtime's domain), or combining --dp-size > 1 with --tp-size > 1, which the DP encoder topology does not support.","commonSituations":"Trying to scale the encoder with tensor parallelism while in DP mode; migrating a TP deployment to DP without removing --tp-size; defaults where tp_size is inherited from a shared config.","solutions":["Set --tp-size 1 and keep --dp-size > 1 for DP encoder mode","For TP encoder scaling, use launch_local_runtime with --dp-size 1 instead","Audit shared launch scripts so tp_size is not silently carried over into DP deployments"],"exampleFix":"# before\n--dp-size 4 --tp-size 4\n# after\n--dp-size 4 --tp-size 1","handlingStrategy":"validation","validationCode":"p = get_parallel()\nassert p.dp_size > 1 and p.tp_size == 1, 'DP encoder needs dp>1, tp=1'","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Validate parallel config before launch","Never carry --tp-size over from TP deployments into DP mode","Add a startup preflight check for flag compatibility"],"tags":["startup","config","dp-size","tp-size","parallelism"],"backgroundTag":"invalid-launch-configuration","analyzedSha":"0132848349585cfe6aae51c4941cbae872505f8a","analyzedAt":"2026-08-28T05:10:05.995Z","schemaVersion":2},"datasetVersion":"2026-08-28T06:17:29.519Z"}