ginuerzh/gost · error

wrong connection type

Error message

wrong connection type

What it means

http2 connector's ConnectContext asserts that the passed connection is a *http2ClientConn; if the type assertion fails it returns 'wrong connection type'. This connector only knows how to issue HTTP/2 CONNECT requests over its own client-connection type, so passing any other net.Conn (e.g. a plain TCP conn or an http2Conn) is rejected up front. It is a programming/wiring error, not a network failure.

Source

Thrown at http2.go:57

func (c *http2Connector) 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)
	}

	opts := &ConnectOptions{}
	for _, option := range options {
		option(opts)
	}
	ua := opts.UserAgent
	if ua == "" {
		ua = DefaultUserAgent
	}

	cc, ok := conn.(*http2ClientConn)
	if !ok {
		return nil, errors.New("wrong connection type")
	}

	pr, pw := io.Pipe()
	req := &http.Request{
		Method:        http.MethodConnect,
		URL:           &url.URL{Scheme: "https", Host: cc.addr},
		Header:        make(http.Header),
		Proto:         "HTTP/2.0",
		ProtoMajor:    2,
		ProtoMinor:    0,
		Body:          pr,
		Host:          address,
		ContentLength: -1,
	}
	req.Header.Set("User-Agent", ua)

	user := opts.User
	if user == nil {

View on GitHub (pinned to a33fdbf4c9)

Solutions

  1. Ensure the conn passed to Connect comes from the same http2 connector's Dial (a *http2ClientConn)
  2. Fix chain wiring so the http2 node uses the http2 dialer/transport, not a plain TCP dialer
  3. Check node/chain configuration (scheme http2 vs http/tcp) so connector and transport match
  4. Log the concrete type of the conn (%T) at the call site to find where the wrong conn originates

Example fix

// before
conn, _ := net.Dial("tcp", addr)
c, err := h2Connector.Connect(ctx, conn, address) // wrong connection type
// after
clientConn, err := h2Connector.Dial(ctx, address, opts) // produces *http2ClientConn
c, err := h2Connector.Connect(ctx, clientConn, address)
Defensive patterns

Strategy: type-guard

Validate before calling

// Before calling Connect, ensure the conn came from the same http2 dialer
if _, ok := conn.(*http2ClientConn); !ok {
    return fmt.Errorf("http2 Connect requires *http2ClientConn, got %T", conn)
}

Type guard

func isHTTP2ClientConn(c net.Conn) (*http2ClientConn, bool) {
    cc, ok := c.(*http2ClientConn)
    return cc, ok
}

Try / catch

c, err := connector.Connect(ctx, conn, address)
if err != nil {
    if err.Error() == "wrong connection type" {
        return nil, fmt.Errorf("wiring bug: conn is %T, expected *http2ClientConn", conn)
    }
    return nil, err
}

Prevention

When it happens

Trigger: Calling gost's http2 Connect(ctx, conn, address) with a connection that was not produced by the http2 connector's own Dial (i.e. not a *http2ClientConn) — for example reusing a generic dialer's conn or mixing up http and http2 connector instances.

Common situations: Building custom chains where the wrong connector gets paired with a transport's connection; refactors that swap http2 dialer for tcp/relay but keep the http2 connector; passing an http2Conn (server-side stream) into a client Connect call.

Related errors


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