ginuerzh/gost · error

%s unsupported

Error message

%s unsupported

What it means

The SNI connector's ConnectContext (sni.go:41) rejects any network type other than TCP. SNI (Server Name Indication) tunneling is implemented over TCP streams only, so passing "udp", "udp4", or "udp6" returns this error immediately without attempting a connection.

Source

Thrown at sni.go:41

)

type sniConnector struct {
	host string
}

// SNIConnector creates a Connector for SNI proxy client.
func SNIConnector(host string) Connector {
	return &sniConnector{host: host}
}

func (c *sniConnector) Connect(conn net.Conn, address string, options ...ConnectOption) (net.Conn, error) {
	return c.ConnectContext(context.Background(), conn, "tcp", address, options...)
}

func (c *sniConnector) ConnectContext(ctx context.Context, conn net.Conn, network, address string, options ...ConnectOption) (net.Conn, error) {
	switch network {
	case "udp", "udp4", "udp6":
		return nil, fmt.Errorf("%s unsupported", network)
	}

	return &sniClientConn{addr: address, host: c.host, Conn: conn}, nil
}

type sniHandler struct {
	options *HandlerOptions
}

// SNIHandler creates a server Handler for SNI proxy server.
func SNIHandler(opts ...HandlerOption) Handler {
	h := &sniHandler{}
	h.Init(opts...)

	return h
}

func (h *sniHandler) Init(options ...HandlerOption) {

View on GitHub (pinned to a33fdbf4c9)

Solutions

  1. Pass "tcp" (or "tcp4"/"tcp6") as the network argument when using the SNI connector
  2. Remove the SNI connector from any path that must carry UDP traffic and use a UDP-capable connector instead
  3. Normalize/validate the network string at the call site before dialing so it cannot be a UDP variant

Example fix

// before
conn, err := connector.ConnectContext(ctx, rawConn, "udp", "example.com:443") // %s unsupported
// after
conn, err := connector.ConnectContext(ctx, rawConn, "tcp", "example.com:443")
Defensive patterns

Strategy: validation

Validate before calling

func validateSNINetwork(network string) error {
    switch network {
    case "", "tcp", "tcp4", "tcp6":
        return nil
    default:
        return fmt.Errorf("SNI connector requires TCP, got %q", network)
    }
}
// call before ConnectContext
if err := validateSNINetwork(network); err != nil { return err }

Type guard

func isTCPNetwork(network string) bool {
    return network == "" || network == "tcp" || network == "tcp4" || network == "tcp6"
}

Try / catch

conn, err := sniConnector.ConnectContext(ctx, rawConn, network, addr)
if err != nil {
    if strings.Contains(err.Error(), " unsupported") {
        return fmt.Errorf("SNI does not support %q; use tcp or a UDP-capable connector", network)
    }
    return err
}

Prevention

When it happens

Trigger: Calling sniConnector.ConnectContext (directly or via the convenience Connect wrapper) with network set to "udp", "udp4", or "udp6" instead of "tcp"/"tcp4"/"tcp6" or an empty string.

Common situations: Configuring a proxy chain where a UDP-based protocol is routed through the SNI connector; code that iterates network types generically ("tcp", "udp") and hits the SNI hop; typos like "UDP" capitalized elsewhere that fall through to a UDP default upstream; misunderstanding SNI as a general-purpose transport.

Related errors


AI-assisted analysis of ginuerzh/gost@a33fdbf4c9 (2026-09-02). Data as JSON: /api/errors/73162f0254aaa756. Report an issue: GitHub.