sgl-project/sglang · critical · ValueError

Unsupported DisaggregationMode: {disaggregation_mode}

Error message

Unsupported DisaggregationMode: {disaggregation_mode}

What it means

The Ascend transfer engine wrapper only accepts PREFILL or DECODE roles from DisaggregationMode during construction; any other value (e.g. NONE or None) logs and raises ValueError. The role string feeds the underlying engine.initialize call, so an invalid mode must fail fast.

Source

Thrown at python/sglang/srt/disaggregation/ascend/transfer_engine.py:50

        if import_error is not None:
            logger.warning(
                "Please install memfabric_hybrid, for details, see docs/docs/advanced_features/pd_disaggregation.mdx"
            )
            raise import_error

        self.engine = TransferEngine()
        self.hostname = hostname
        self.npu_id = npu_id

        # Centralized storage address of the AscendTransferEngine
        self.store_url = os.getenv("ASCEND_MF_STORE_URL")
        if disaggregation_mode == DisaggregationMode.PREFILL:
            self.role = "Prefill"
        elif disaggregation_mode == DisaggregationMode.DECODE:
            self.role = "Decode"
        else:
            logger.error(f"Unsupported DisaggregationMode: {disaggregation_mode}")
            raise ValueError(f"Unsupported DisaggregationMode: {disaggregation_mode}")
        rpc_port = self.engine.get_rpc_port()
        self.session_id = NetworkAddress(self.hostname, rpc_port).to_host_port_str()
        self.initialize()
        if rpc_port == 0:
            rpc_port = self.engine.get_rpc_port()
            self.session_id = NetworkAddress(self.hostname, rpc_port).to_host_port_str()

    def initialize(self) -> None:
        from sglang.srt.distributed.parallel_state import (
            get_world_group,
            get_world_size,
        )

        transfer_protocol = self._get_transfer_protocol()
        if transfer_protocol is None or transfer_protocol == "sdma":
            trans_op_type = TransferEngine.TransDataOpType.SDMA
        else:
            trans_op_type = TransferEngine.TransDataOpType.DEVICE_RDMA

View on GitHub (pinned to 0132848349)

Solutions

  1. Set --disaggregation-mode prefill on the prefill instance and decode on the decode instance
  2. Only construct the Ascend transfer engine on nodes actually participating in PD disaggregation
  3. Guard construction: skip when disaggregation_mode is NONE

Example fix

# before
engine = AscendTransferEngine(...)  # mode defaults to NONE
# after
engine = (AscendTransferEngine(..., disaggregation_mode=DisaggregationMode.PREFILL)
          if args.disaggregation_mode != DisaggregationMode.NONE else None)
Defensive patterns

Strategy: validation

Validate before calling

from sglang.srt.disaggregation import DisaggregationMode\nassert disaggregation_mode in (DisaggregationMode.PREFILL, DisaggregationMode.DECODE), 'set --disaggregation-mode'

Type guard

def is_pd_mode(m) -> bool:\n    return m in (DisaggregationMode.PREFILL, DisaggregationMode.DECODE)

Prevention

When it happens

Trigger: Constructing AscendTransferEngine with disaggregation_mode=DisaggregationMode.NONE (the default when disaggregation is not enabled), or a None/invalid mode value.

Common situations: Server launched without --disaggregation-mode prefill|decode but the Ascend PD component still gets constructed; typos or missing config plumbing in custom launch scripts; component instantiated unconditionally in a code path that also runs in non-PD mode.

Related errors


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