sgl-project/sglang · error · ValueError

grpcs:// is not supported; use grpc://

Error message

grpcs:// is not supported; use grpc://

What it means

Raised by _grpc_target when an encoder URL uses the grpcs:// (TLS) scheme. The gRPC encoder client in SGLang's disaggregated encoder path only supports plaintext grpc:// targets; TLS-secured gRPC connections are not implemented, so the URL is rejected rather than silently downgraded.

Source

Thrown at python/sglang/srt/disaggregation/encoder/receiver.py:347

            self._server.run()
        except Exception as e:
            logger.error(f"EncoderBootstrapServer error: {e}", exc_info=True)

    def close(self):
        if self._server is not None:
            # uvicorn polls should_exit on its own event loop; thread-safe.
            self._server.should_exit = True
            logger.info("Stopping EncoderBootstrapServer...")
        if self.thread.is_alive():
            self.thread.join(timeout=5)
            logger.info("EncoderBootstrapServer thread stopped")


def _grpc_target(url: str) -> str:
    if url.startswith("grpc://"):
        return url[len("grpc://") :]
    if url.startswith("grpcs://"):
        raise ValueError("grpcs:// is not supported; use grpc://")
    return url


def _normalize_embedding_ports(embedding_port):
    if embedding_port is None:
        return []
    if isinstance(embedding_port, list):
        return embedding_port
    return [embedding_port]


def _grpc_scheduler_receive_url(target, req_id, receive_url, receive_count):
    import grpc
    from smg_grpc_proto import sglang_encoder_pb2, sglang_encoder_pb2_grpc

    timeout_secs = envs.SGLANG_ENCODER_GRPC_TIMEOUT_SECS.get()
    channel = grpc.insecure_channel(target)
    stub = sglang_encoder_pb2_grpc.SglangEncoderStub(channel)

View on GitHub (pinned to 0132848349)

Solutions

  1. Change grpcs://host:port to grpc://host:port in encoder URL configuration.
  2. If TLS is required, terminate TLS at a sidecar/proxy (e.g. Envoy, nginx, or stunnel) and point SGLang at the plaintext grpc:// proxy address.
  3. Ensure the encoder service itself is listening on plaintext gRPC on that port.

Example fix

# before
--encoder-urls grpcs://encoder0:9000
# after
--encoder-urls grpc://encoder0:9000  # terminate TLS in a proxy if needed
Defensive patterns

Strategy: validation

Validate before calling

def validate_encoder_url(url: str) -> str:
    if url.startswith("grpcs://"):
        raise ValueError(f"{url}: TLS gRPC unsupported; use grpc:// (terminate TLS at a proxy)")
    return url

urls = [validate_encoder_url(u) for u in urls]

Try / catch

try:
    target = _grpc_target(url)
except ValueError as e:
    logger.error("encoder URL rejected: %s", e)
    target = url.removeprefix("grpcs://")  # only if backend truly is plaintext behind a TLS proxy

Prevention

When it happens

Trigger: Configuring encode_urls / encoder URLs like grpcs://encoder:9000 and invoking send_embedding_port or encode, which call _grpc_target to normalize the URL before creating the gRPC channel.

Common situations: Deployments that copy a TLS-enabled gRPC endpoint (common in service meshes or cloud-hosted encoders) into SGLang encoder config; mixing up HTTPS-style URLs with the gRPC scheme.

Related errors


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