sgl-project/sglang · critical · RuntimeError

{name} port {port} is unavailable and --strict-ports is enab

Error message

{name} port {port} is unavailable and --strict-ports is enabled. Either use a different port or disable --strict-ports.

What it means

Under --strict-ports, the server probes each requested port and fails fast if one is already bound (is_port_available returns False). This is a RuntimeError raised during network-port adjustment, before server start.

Source

Thrown at python/sglang/multimodal_gen/runtime/server_args/server_args.py:1201

        # BCG captures every graph during a synthetic warmup forward at startup
        # so serving never records a fresh graph.
        if self.enable_breakable_cuda_graph and self.disagg_role == RoleType.MONOLITHIC:
            self.warmup_mode = "server"

        # Disaggregated roles do not host the HTTP startup request. Preserve
        # warmup intent, but schedule it on the first request instead.
        if self.disagg_role != RoleType.MONOLITHIC and self.warmup_mode == "server":
            self.warmup_mode = "request"

        if self.warmup_mode is None:
            self.warmup_mode = "off"

    @staticmethod
    def _require_port(port: int, name: str) -> None:
        """Raise if *port* is occupied (used under ``--strict-ports``)."""
        if not is_port_available(port):
            raise RuntimeError(
                f"{name} port {port} is unavailable and --strict-ports is enabled. "
                f"Either use a different port or disable --strict-ports."
            )

    def _adjust_network_ports(self):
        # Disagg role instances (encoder/denoiser/decoder) don't serve HTTP,
        # so skip settling the HTTP port to avoid unnecessary port collisions.
        needs_http = self.disagg_role in (
            RoleType.MONOLITHIC,
            RoleType.SERVER,
        )

        if self.strict_ports:
            requested_ports = []
            if needs_http:
                requested_ports.append((self.port, "HTTP"))
            for replica in range(self.dp_size or 1):
                requested_ports.append(

View on GitHub (pinned to 0132848349)

Solutions

  1. Free the port: stop the old process (lsof -i :PORT / kill) or wait for socket release
  2. Choose different ports (--port, --master-port, etc.)
  3. Drop --strict-ports to let the server pick/ignore availability (only if acceptable)

Example fix

# before
python -m ... --port 30000 --strict-ports  # port 30000 busy
# after
python -m ... --port 30001 --strict-ports
Defensive patterns

Strategy: fallback

Validate before calling

import socket

def port_free(port: int) -> bool:
    with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
        s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
        return s.connect_ex(('127.0.0.1', port)) != 0

Try / catch

try:
    args.resolve()  # or ServerArgs construction
except RuntimeError as e:
    if 'unavailable and --strict-ports' in str(e):
        args.port += 1  # retry with next port
    else:
        raise

Prevention

When it happens

Trigger: Starting a second instance while the first still holds the port; a crashed process leaving a socket in TIME_WAIT; container port already allocated; --port/--master-port colliding with another service.

Common situations: Dev loops restarting the server while the old one is shutting down; CI runners with occupied ports; port-forwarding setups where the host port is taken.

Related errors


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