openimsdk/open-im-server · error

failed to dial endpoint %s: %v

Error message

failed to dial endpoint %s: %v

What it means

After obtaining endpoint addresses, initializeConns dials each pod's IP:port with grpc.Dial. If a dial fails, it wraps the target address and underlying error. Note grpc.Dial is usually non-blocking and errors here typically reflect invalid target syntax rather than unreachability, so failures usually indicate malformed addresses.

Source

Thrown at pkg/common/discovery/kubernetes/kubernetes.go:77

	if err != nil {
		return err
	}

	endpoints, err := k.clientset.CoreV1().Endpoints(k.namespace).Get(context.Background(), serviceName, metav1.GetOptions{})
	if err != nil {
		return fmt.Errorf("failed to get endpoints for service %s: %v", serviceName, err)
	}

	// fmt.Println("Endpoints:", endpoints, "endpoints.Subsets:", endpoints.Subsets)

	var conns []*grpc.ClientConn
	for _, subset := range endpoints.Subsets {
		for _, address := range subset.Addresses {
			target := fmt.Sprintf("%s:%d", address.IP, port)
			// fmt.Println("IP target:", target)
			conn, err := grpc.Dial(target, append(k.dialOptions, grpc.WithTransportCredentials(insecure.NewCredentials()))...)
			if err != nil {
				return fmt.Errorf("failed to dial endpoint %s: %v", target, err)
			}
			conns = append(conns, conn)
		}
	}

	k.mu.Lock()
	k.connMap[serviceName] = conns
	k.mu.Unlock()

	return nil
}

// GetConns returns gRPC client connections for a given Kubernetes service name.
func (k *KubernetesConnManager) GetConns(ctx context.Context, serviceName string, opts ...grpc.DialOption) ([]*grpc.ClientConn, error) {
	k.mu.RLock()

	conns, exists := k.connMap[serviceName]
	k.mu.RUnlock()

View on GitHub (pinned to 175a7bb067)

Solutions

  1. Log/verify the target address — an empty or malformed IP in the Endpoints subset is the most common cause.
  2. Check the resolved svcPort matches the container's gRPC listen port.
  3. Verify the pod is ready (endpoints only list ready addresses normally) and reachable from this pod.
  4. Use grpc.NewClient / non-blocking Dial and treat first RPC failure as the connection error instead.

Example fix

// before
conn, err := grpc.Dial(target, append(k.dialOptions, grpc.WithTransportCredentials(insecure.NewCredentials()))...)
// after
conn, err := grpc.NewClient(target, append(k.dialOptions, grpc.WithTransportCredentials(insecure.NewCredentials()))...)
if err != nil {
    log.Printf("skip bad endpoint %s: %v", target, err)
    continue
}
Defensive patterns

Strategy: retry

Validate before calling

if address.IP == "" {
    return errors.New("endpoint subset has empty IP")
}

Type guard

func validTarget(ip string, port int32) bool {
    return net.ParseIP(ip) != nil && port > 0
}

Try / catch

conn, err := grpc.NewClient(target, opts...)
if err != nil {
    return fmt.Errorf("dial %s: %w", target, err)
}

Prevention

When it happens

Trigger: grpc.Dial(fmt.Sprintf("%s:%d", address.IP, port), ...) fails — usually an invalid address string (bad IP from endpoint subset, empty IP) or invalid dial options; with WithBlock it can also be a connection timeout to the pod.

Common situations: Endpoint subsets containing not-ready or placeholder IPs; service port mismatch so the pod refuses connections; passing nil/invalid dial options; port resolved as 0.

Related errors


AI-assisted analysis of openimsdk/open-im-server@175a7bb067 (2026-09-04). Data as JSON: /api/errors/7d2067423d4d455e. Report an issue: GitHub.