sgl-project/sglang · error · ValueError

--ep-dispatch-algorithm {cfg.ep_dispatch_algorithm} picks a

Error message

--ep-dispatch-algorithm {cfg.ep_dispatch_algorithm} picks a different physical replica per rank, which only holds up when an a2a backend routes each token to a single rank. Use --ep-dispatch-algorithm dynamic with --moe-a2a-backend none.

What it means

Raised when --ep-dispatch-algorithm is 'static' or 'lp' while there is no single-rank-routing a2a backend (needs_rank_invariant_dispatch). Those algorithms pick a different physical replica per rank, which is only consistent if each token is routed to exactly one rank; with --moe-a2a-backend none the dispatch must be rank-invariant, so only 'dynamic'/'fake' are allowed.

Source

Thrown at python/sglang/srt/server_args.py:7897

        needs_rank_invariant_dispatch = self._resolved().moe_a2a_backend == "none"

        if (cfg.enable_eplb or (cfg.init_expert_location != "trivial")) and (
            cfg.ep_dispatch_algorithm is None
        ):
            self._declare(
                "_handle_eplb_and_dispatch",
                ep_dispatch_algorithm=(
                    "dynamic" if needs_rank_invariant_dispatch else "static"
                ),
            )

        # `dynamic` / `fake` switch to the row-index pick; `static` reads a
        # per-rank table and `lp` samples inside its kernel.
        if needs_rank_invariant_dispatch and cfg.ep_dispatch_algorithm in (
            "static",
            "lp",
        ):
            raise ValueError(
                f"--ep-dispatch-algorithm {cfg.ep_dispatch_algorithm} picks a "
                "different physical replica per rank, which only holds up when an "
                "a2a backend routes each token to a single rank. Use "
                "--ep-dispatch-algorithm dynamic with --moe-a2a-backend none."
            )

        if cfg.enable_eplb and cfg.ep_join_mode != "scale":
            assert self._resolved().ep_size > 1

    def _handle_elastic_ep(self):
        cfg = resolving_view(self)
        if cfg.elastic_ep_rejoin:
            if cfg.ep_join_mode is None:
                logger.warning(
                    "--elastic-ep-rejoin is deprecated, use --elastic-ep-join-mode recover instead."
                )
                self._declare(
                    "_handle_elastic_ep",

View on GitHub (pinned to 0132848349)

Solutions

  1. Set --ep-dispatch-algorithm dynamic when using --moe-a2a-backend none
  2. Enable an a2a backend (e.g. --moe-a2a-backend deepep) so single-rank routing holds and static/lp become valid

Example fix

# before
--moe-a2a-backend none --ep-dispatch-algorithm lp
# after
--moe-a2a-backend none --ep-dispatch-algorithm dynamic
Defensive patterns

Strategy: validation

Validate before calling

if ep_dispatch_algorithm in ("static", "lp") and moe_a2a_backend == "none":
    ep_dispatch_algorithm = "dynamic"

Prevention

When it happens

Trigger: Configuring --ep-dispatch-algorithm static or lp together with --moe-a2a-backend none (or any config where needs_rank_invariant_dispatch is true).

Common situations: Tuning EPLB dispatch for locality/power-aware placement with the a2a backend disabled; reusing an EPLB-tuned config on a single-node deployment that runs MoE without a2a.

Related errors


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