sgl-project/sglang · critical · ValueError

Unsupported DisaggregationMode: {self.disaggregation_mode}

Error message

Unsupported DisaggregationMode: {self.disaggregation_mode}

What it means

The common (shared) PD connection object only supports PREFILL and DECODE disaggregation modes; its __init__ sets up prefill-side executors for the prefill branch and decode-side state otherwise, and raises ValueError for any other DisaggregationMode value.

Source

Thrown at python/sglang/srt/disaggregation/common/conn.py:291

            self.max_failures = max(
                envs.SGLANG_DISAGGREGATION_HEARTBEAT_MAX_FAILURE.get(), 1
            )
            # If a timeout happens on the decode side, it means decode instances
            # fail to receive the KV Cache transfer done signal after bootstrapping.
            # These timeout requests should be aborted to release the tree cache.
            self.waiting_timeout = envs.SGLANG_DISAGGREGATION_WAITING_TIMEOUT.get()
            # PD true-retraction rebootstrap: a shared executor + per-thread HTTP
            # sessions used to drive the original prefill worker's ``/generate``
            # endpoint so it recomputes a retracted request's prefix KV under the
            # current weights. Created lazily on first use so deployments that
            # never retract pay nothing.
            self._prefill_recompute_executor: Optional[
                concurrent.futures.ThreadPoolExecutor
            ] = None
            self._prefill_recompute_executor_lock = threading.Lock()
            self._prefill_recompute_sessions = threading.local()
        else:
            raise ValueError(
                f"Unsupported DisaggregationMode: {self.disaggregation_mode}"
            )

    def _should_skip_cp_replicated_state_transfer(self) -> bool:
        """Whether this prefill rank should omit CP-replicated state.

        Prefill CP materializes global token order before writing state pools, so
        every CP rank holds the same state. When all CP ranks transfer their KV
        shards, only rank 0 needs to send that state. Cache layer split is the
        exception because each CP rank owns different state layers.
        """
        return (
            self.attn_cp_size > 1
            and self.attn_cp_rank != 0
            and not get_parallel().enable_dsa_cache_layer_split
        )

    def requires_dcp_relayout(self, dst_dcp_size: int, dst_dcp_rank: int) -> bool:

View on GitHub (pinned to 0132848349)

Solutions

  1. Pass --disaggregation-mode prefill or decode explicitly on every PD node
  2. Only instantiate the connection when the server is in PD mode; gate on disaggregation_mode != DisaggregationMode.NONE
  3. Check argument parsing if the CLI value is silently dropped before reaching the connection

Example fix

# before
conn = PDConnection(args...)  # args.disaggregation_mode == NONE
# after
conn = PDConnection(args...) if args.disaggregation_mode != DisaggregationMode.NONE else None
Defensive patterns

Strategy: validation

Validate before calling

if disaggregation_mode not in (DisaggregationMode.PREFILL, DisaggregationMode.DECODE):\n    raise SystemExit('PD connection requires --disaggregation-mode prefill|decode')

Prevention

When it happens

Trigger: Constructing the common PD connection class with disaggregation_mode set to NONE (or None) — i.e. the connection object is instantiated although the server is not in PD mode.

Common situations: Code path that unconditionally builds the disaggregation connection even in normal (non-PD) serving; missing or mis-parsed --disaggregation-mode argument; test harness constructing the object with a default mode.

Related errors


AI-assisted analysis of sgl-project/sglang@0132848349 (2026-08-28). Data as JSON: /api/errors/5e2718ad8fd0e77b. Report an issue: GitHub.