grpc/grpc-go · error

grpctransport: failed to create connection to server %q: %v

Error message

grpctransport: failed to create connection to server %q: %v

What it means

After all validations pass, Build calls the gRPC new-client function (grpc.NewClient by default, or a custom GRPCNewClient) with the server URI and dial options including the credentials bundle and keepalive params (grpc_transport.go:135-137). If that call returns an error, it is wrapped with the server URI. This is a connection-creation failure, not a connection-establishment failure — grpc.NewClient is lazy, so most errors here come from invalid dial options or a custom client function.

Source

Thrown at internal/xds/clients/grpctransport/grpc_transport.go:137

		return tr, nil
	}

	// Create a new gRPC client/channel for the server with the provided
	// credentials, server URI, and a byte codec to send and receive messages.
	// Also set a static keepalive configuration that is common across gRPC
	// language implementations.
	kpCfg := grpc.WithKeepaliveParams(keepalive.ClientParameters{
		Time:    5 * time.Minute,
		Timeout: 20 * time.Second,
	})
	dopts := []grpc.DialOption{kpCfg, grpc.WithCredentialsBundle(config.Credentials), grpc.WithDefaultCallOptions(grpc.ForceCodec(&byteCodec{}))}
	newClientFunc := grpc.NewClient
	if config.GRPCNewClient != nil {
		newClientFunc = config.GRPCNewClient
	}
	cc, err := newClientFunc(si.ServerURI, dopts...)
	if err != nil {
		return nil, fmt.Errorf("grpctransport: failed to create connection to server %q: %v", si.ServerURI, err)
	}
	tr := &grpcTransport{cc: cc}
	// Register a cleanup function that decrements the refs to the gRPC
	// transport each time Close() is called to close it and remove from
	// transports and connections map if last reference is being released.
	tr.cleanup = b.cleanupFunc(si, tr)

	// Add the newly created connection to the maps to re-use the transport
	// channel and track references.
	b.connections[si] = cc
	b.refs[si] = 1

	if logger.V(2) {
		logger.Infof("Created a new transport to the server for ServerIdentifier: %v", si)
	}
	return tr, nil
}

View on GitHub (pinned to 03255a9237)

Solutions

  1. Inspect the wrapped error (%v) — it distinguishes option errors from URI/resolver errors from custom-client errors.
  2. If using a custom GRPCNewClient, test it in isolation with the same target and options.
  3. Verify the ServerURI scheme (dns:///, xds:///, etc.) is supported and well-formed.
  4. Confirm the credentials bundle is compatible with the transport; remove conflicting DialOptions.
  5. For transient network issues inside a custom client, consider retrying Build after a backoff.

Example fix

// before:
//   builder with a custom GRPCNewClient that dials eagerly and fails
// after:
//   test the custom client separately:
//   cc, err := myClientFunc("dns:///xds:443", dopts...)
//   if err != nil { log.Printf("dial option error: %v", err) }
//   // or simplify by using the default grpc.NewClient (GRPCNewClient = nil)
Defensive patterns

Strategy: try-catch

Validate before calling

// If using a custom GRPCNewClient, sanity-check the target first.
func validateTarget(uri string) error {
    if uri == "" { return errors.New("empty target") }
    // ensure the scheme is recognized by the gRPC resolver registry
    return nil
}

Try / catch

tr, err := builder.Build(si)
if err != nil {
    if strings.Contains(err.Error(), "failed to create connection") {
        // inspect wrapped cause; retry transient failures after backoff
        return fmt.Errorf("transport build failed for %q: %w", si.ServerURI, err)
    }
    return err
}

Prevention

When it happens

Trigger: grpc.NewClient (or a custom GRPCNewClient) returns a non-nil error — typically because a DialOption is invalid (e.g. conflicting credentials), the target URI is malformed in a way the resolver rejects immediately, or a custom new-client function has its own precondition that failed.

Common situations: The credentials bundle is incompatible with the target scheme; a custom GRPCNewClient performs eager validation or dialing and the server is unreachable; the ServerURI uses a scheme/resolver that errors at construction; environment (proxy) settings interfere with name resolution at client creation.

Related errors


AI-assisted analysis of grpc/grpc-go@03255a9237 (2026-08-07). Data as JSON: /api/errors/cf9a6a3e3a196e69. Report an issue: GitHub.