valyala/fasthttp · error

dialling unsuccessful: please report this bug

Error message

dialling unsuccessful: please report this bug

What it means

This error is returned when the configured dial function returns both a nil error and a nil connection — an impossible result indicating a bug. fasthttp treats it as a programming error in the DialFunc and asks for a bug report.

Source

Thrown at client.go:2332

	}
	err = conn.SetDeadline(time.Time{})
	if err != nil {
		return nil, err
	}
	return conn, nil
}

func dialAddr(
	addr string, dial DialFunc, dialWithTimeout DialFuncWithTimeout, dialDualStack, isTLS bool,
	tlsConfig *tls.Config, dialTimeout, writeTimeout time.Duration,
) (net.Conn, error) {
	deadline := time.Now().Add(writeTimeout)
	conn, err := callDialFunc(addr, dial, dialWithTimeout, dialDualStack, isTLS, dialTimeout)
	if err != nil {
		return nil, err
	}
	if conn == nil {
		return nil, errors.New("dialling unsuccessful: please report this bug")
	}

	// We assume that any conn that has the Handshake() method is a TLS conn already.
	// This doesn't cover just tls.Conn but also other TLS implementations.
	_, isTLSAlready := conn.(interface{ Handshake() error })

	if isTLS && !isTLSAlready {
		if writeTimeout == 0 {
			return tls.Client(conn, tlsConfig), nil
		}
		return tlsClientHandshake(conn, tlsConfig, deadline)
	}
	return conn, nil
}

func callDialFunc(
	addr string, dial DialFunc, dialWithTimeout DialFuncWithTimeout, dialDualStack, isTLS bool, timeout time.Duration,
) (net.Conn, error) {

View on GitHub (pinned to c96f600972)

Solutions

  1. Fix the custom DialFunc so every path returns either a non-nil conn or a non-nil error
  2. Audit wrapped/proxied dialers for paths that return nil, nil (often after type assertions)
  3. If using the library's default dial chain with no custom dials, report the bug to fasthttp with a reproducer
  4. Add a defensive assertion/log at the dialer boundary to catch nil, nil during development

Example fix

// before (buggy custom dialer)
func dial(addr string) (net.Conn, error) {
    c, err := net.Dial("tcp", addr)
    if err != nil { return nil, err }
    if bad(c) { return } // returns nil, nil!
    return c, nil
}
// after
func dial(addr string) (net.Conn, error) {
    c, err := net.Dial("tcp", addr)
    if err != nil { return nil, err }
    if bad(c) { return nil, errors.New("dial: unusable conn") }
    return c, nil
}
Defensive patterns

Strategy: validation

Validate before calling

conn, err := dialFn(addr)
if err == nil && conn == nil {
    return nil, errors.New("dialer bug: returned nil conn with nil error")
}

Type guard

func validDialResult(c net.Conn, err error) bool {
    return (err == nil) == (c != nil)
}

Try / catch

if err != nil && strings.Contains(err.Error(), "dialling unsuccessful") {
    // do not retry; fix the DialFunc
}

Prevention

When it happens

Trigger: A custom Client.Dial / DialFunc (or the dial, dialWithTimeout, dialDualStack wrapper chain in callDialFunc) returns (nil, nil) instead of either a valid net.Conn or a non-nil error.

Common situations: Custom dialers with code paths that forget to return the connection (e.g. early return after a failed cast); buggy wrapped or third-party dial implementations.

Related errors


AI-assisted analysis of valyala/fasthttp@c96f600972 (2026-08-31). Data as JSON: /api/errors/487ab64612286ad0. Report an issue: GitHub.