micro/go-micro · error

reflect grpc target %s: %w

Error message

reflect grpc target %s: %w

What it means

After connecting, reflectedGRPCTools calls loadReflectedFiles to perform gRPC server reflection (list services + fetch file descriptors). Any failure inside reflection is wrapped with the target address in this error. The connection itself succeeded; the reflection RPC exchange failed.

Source

Thrown at gateway/mcp/grpcreflect.go:74

	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
		}
		svc, ok := desc.(protoreflect.ServiceDescriptor)
		if !ok {
			continue
		}
		for i := 0; i < svc.Methods().Len(); i++ {

View on GitHub (pinned to 24529f1404)

Solutions

  1. Enable reflection on the target server: reflection.Register(server) after NewServer, or run with a reflection-enabled option.
  2. Verify the wrapped (%w) inner error to distinguish NotFound (no reflection service) from timeouts/cancellations.
  3. Check network reachability and that ctx is not cancelled before loadReflectedFiles completes.
  4. If the server cannot enable reflection, provide descriptor files instead of relying on reflection discovery.

Example fix

// before
server := grpc.NewServer()
server.Serve(lis) // no reflection
// after
server := grpc.NewServer()
reflection.Register(server)
server.Serve(lis)
Defensive patterns

Strategy: fallback

Validate before calling

// probe reflection support before full discovery
conn, _ := grpc.NewClient(addr, grpc.WithTransportCredentials(insecure.NewCredentials()))
client := grpcreflection.NewReflectionClientAuto(conn)
ctx, cancel := context.WithTimeout(context.Background(), 3*time.Second)
defer cancel()
if _, err := client.ListServices(ctx, &refpb.ListServicesRequest{}); err != nil {
    return fmt.Errorf("target %s lacks reflection: %w", addr, err)
}

Try / catch

tools, err := reflectedGRPCTools(ctx, target)
if err != nil && strings.Contains(err.Error(), "reflect grpc target") {
    tools = loadToolsFromStaticDescriptors(target) // fallback path
}

Prevention

When it happens

Trigger: grpc.NewClient succeeds but loadReflectedFiles fails: the server does not implement gRPC reflection, reflection RPCs time out, or the reflection stream returns an error.

Common situations: Target server was started without grpc reflection (reflection.Register(server) missing or grpcui not enabled); a proxy/firewall blocking the reflection service; server shutting down mid-reflection.

Related errors


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