hyperledger/fabric · error

failed to create new connection

Error message

failed to create new connection

What it means

Comm.ClientConfig.Dial wraps grpc.DialContext with a dial timeout; when the underlying gRPC dial fails (DNS resolution failure, connection refused, TLS handshake setup, context deadline), it wraps the error with 'failed to create new connection'. The root cause is always embedded in the wrapped error.

Source

Thrown at internal/pkg/comm/config.go:178

	} else {
		dialOpts = append(dialOpts, grpc.WithTransportCredentials(insecure.NewCredentials()))
	}

	return dialOpts, nil
}

func (cc ClientConfig) Dial(address string) (*grpc.ClientConn, error) {
	dialOpts, err := cc.DialOptions()
	if err != nil {
		return nil, err
	}

	ctx, cancel := context.WithTimeout(context.Background(), cc.DialTimeout)
	defer cancel()

	conn, err := grpc.DialContext(ctx, address, dialOpts...)
	if err != nil {
		return nil, errors.Wrap(err, "failed to create new connection")
	}
	return conn, nil
}

// Clone clones this ClientConfig
func (cc ClientConfig) Clone() ClientConfig {
	shallowClone := cc
	return shallowClone
}

// SecureOptions defines the TLS security parameters for a GRPCServer or
// GRPCClient instance.
type SecureOptions struct {
	// VerifyCertificate, if not nil, is called after normal
	// certificate verification by either a TLS client or server.
	// If it returns a non-nil error, the handshake is aborted and that error results.
	VerifyCertificate func(rawCerts [][]byte, verifiedChains [][]*x509.Certificate) error
	// PEM-encoded X509 public key to be used for TLS communication

View on GitHub (pinned to 2736b63f8f)

Solutions

  1. Inspect the wrapped cause (errors.Cause / %v of the returned error) — it names the real failure (refused, timeout, DNS, TLS).
  2. Verify the peer address:port is correct and reachable (nc -vz host port).
  3. Increase cc.DialTimeout in ClientConfig if the network is slow.
  4. If TLS is enabled, confirm serverNameOverride and the root CA cert match the peer's certificate.
  5. Ensure the peer process/container is running and the port is exposed.

Example fix

// before
conn, err := grpc.DialContext(ctx, address, dialOpts...) // default short timeout
// after
cc.DialTimeout = 15 * time.Second
conn, err := comm.NewClientConfig(...).Dial(address) // log errors.Wrap cause, retry transient failures
Defensive patterns

Strategy: try-catch

Validate before calling

// pre-flight reachability check before Dial
host, port, _ := net.SplitHostPort(address)
if conn, err := net.DialTimeout("tcp", net.JoinHostPort(host, port), 3*time.Second); err != nil {
    return fmt.Errorf("peer %s unreachable: %w", address, err)
} else { conn.Close() }

Type guard

func isConnFailure(err error) bool {
    return err != nil && strings.Contains(err.Error(), "failed to create new connection")
}

Try / catch

conn, err := cc.Dial(address)
if err != nil {
    // unwrap the grpc cause
    return fmt.Errorf("dial %s: %v", address, errors.Unwrap(err))
    // retry with backoff only for transient causes (timeout, unavailable)
}

Prevention

When it happens

Trigger: Dialing an unreachable/wrong peer address or port; DNS failure for the peer hostname; dial timeout exceeded (ConnectionTimeout too small); TLS config mismatch preventing connection setup.

Common situations: Peer container not running or wrong port in config; Kubernetes service DNS names unresolvable from the client; firewalls blocking the gRPC port; certificate hostname mismatches with TLS enabled; slow networks exceeding DialTimeout.

Related errors


AI-assisted analysis of hyperledger/fabric@2736b63f8f (2026-09-04). Data as JSON: /api/errors/988454f3679b140b. Report an issue: GitHub.