micro/go-micro · error

connect reflected grpc target %s: %w

Error message

connect reflected grpc target %s: %w

What it means

reflectedGRPCTools establishes a gRPC client connection to the configured reflection target using grpc.NewClient with the target's DialOptions (defaulting to insecure credentials). If client creation fails, the error is wrapped with the target address. This is the entry point for discovering tools via gRPC server reflection.

Source

Thrown at gateway/mcp/grpcreflect.go:68

	}
	return nil
}

func (s *Server) reflectedGRPCTools(target ReflectedGRPCTarget) ([]*Tool, error) {
	timeout := target.Timeout
	if timeout == 0 {
		timeout = 10 * time.Second
	}
	ctx, cancel := context.WithTimeout(s.opts.Context, timeout)
	defer cancel()

	dialOpts := target.DialOptions
	if len(dialOpts) == 0 {
		dialOpts = []grpc.DialOption{grpc.WithTransportCredentials(insecure.NewCredentials())}
	}
	conn, err := grpc.NewClient(target.Address, dialOpts...)
	if err != nil {
		return nil, fmt.Errorf("connect reflected grpc target %s: %w", target.Address, err)
	}
	defer conn.Close()

	files, services, err := loadReflectedFiles(ctx, conn)
	if err != nil {
		return nil, fmt.Errorf("reflect grpc target %s: %w", target.Address, err)
	}

	prefix := target.Name
	if prefix == "" {
		prefix = sanitizeToolPart(target.Address)
	}

	var out []*Tool
	for _, serviceName := range services {
		desc, err := files.FindDescriptorByName(protoreflect.FullName(serviceName))
		if err != nil {
			continue

View on GitHub (pinned to 24529f1404)

Solutions

  1. Check the wrapped (%w) grpc error; correct target.Address format (e.g. 'dns:///host:port' or 'host:port').
  2. Review target.DialOptions for invalid or mutually conflicting options.
  3. If the endpoint is plaintext, either leave DialOptions empty (defaults to insecure) or pass grpc.WithTransportCredentials(insecure.NewCredentials()) explicitly.
  4. Upgrade/verify grpc-go version compatibility if NewClient (added in grpc-go 1.63) behaves differently than grpc.Dial in your setup.

Example fix

// before
target.DialOptions = []grpc.DialOption{grpc.WithTransportCredentials(credentials.NewTLS(nil))}
// after
target.DialOptions = nil // falls back to insecure default, or supply correctly configured TLS creds
Defensive patterns

Strategy: validation

Validate before calling

if target.Address == "" || (!strings.Contains(target.Address, ":") && !strings.Contains(target.Address, "/")) {
    return fmt.Errorf("invalid grpc target address %q", target.Address)
}

Type guard

func validGRPCTarget(t GRPCTarget) bool {
    return t.Address != "" && (len(t.DialOptions) == 0 || t.DialOptions != nil)
}

Try / catch

conn, err := grpc.NewClient(target.Address, dialOpts...)
if err != nil {
    return fmt.Errorf("target %s rejected by grpc.NewClient: %w", target.Address, err)
}
defer conn.Close()

Prevention

When it happens

Trigger: Calling reflectedGRPCTools (via discoverReflectedGRPC) where target.DialOptions are invalid or grpc.NewClient rejects the target.Address/configuration.

Common situations: Malformed target address string (bad scheme/host); unsupported or conflicting grpc.DialOption combinations; attempting TLS credentials against a target that needs a different scheme (dns:/// vs passthrough).

Related errors


AI-assisted analysis of micro/go-micro@24529f1404 (2026-09-01). Data as JSON: /api/errors/4d5c7a988a44564d. Report an issue: GitHub.