micro/go-micro · error
reflection list services returned %T
Error message
reflection list services returned %T
What it means
loadReflectedFiles expects the first message on the reflection stream to be a ListServicesResponse. If the server reflection response carries a different MessageResponse variant (e.g. an ErrorResponse or FileDescriptorResponse), this type-mismatch error is returned, naming the unexpected Go type received.
Source
Thrown at gateway/mcp/grpcreflect.go:126
return out, nil
}
func loadReflectedFiles(ctx context.Context, conn *grpc.ClientConn) (*protoregistryFiles, []string, error) {
client := reflectionpb.NewServerReflectionClient(conn)
stream, err := client.ServerReflectionInfo(ctx)
if err != nil {
return nil, nil, err
}
if err := stream.Send(&reflectionpb.ServerReflectionRequest{MessageRequest: &reflectionpb.ServerReflectionRequest_ListServices{ListServices: ""}}); err != nil {
return nil, nil, err
}
resp, err := stream.Recv()
if err != nil {
return nil, nil, err
}
list := resp.GetListServicesResponse()
if list == nil {
return nil, nil, fmt.Errorf("reflection list services returned %T", resp.MessageResponse)
}
set := &descriptorpb.FileDescriptorSet{}
seen := map[string]bool{}
var services []string
for _, svc := range list.Service {
name := svc.Name
if strings.HasPrefix(name, "grpc.reflection.") {
continue
}
services = append(services, name)
if err := requestFileContainingSymbol(ctx, client, name, set, seen); err != nil {
return nil, nil, err
}
}
files, err := newProtoregistryFiles(set)
if err != nil {
return nil, nil, errView on GitHub (pinned to 24529f1404)
Solutions
- Log the received %T to see which response variant came back (most likely ErrorResponse) and handle its message.
- Ensure the target supports the LIST_SERVICES reflection request (reflection.Register on the server).
- Check the server's reflection/grpc version and upgrade mismatched clients/servers.
- Inspect any proxy between client and server that could alter reflection responses.
Example fix
// before (server) // reflection partially wired; handler returns error for list // after (server) reflection.Register(server) // guarantees ListServicesResponse for LIST_SERVICES
Defensive patterns
Strategy: type-guard
Type guard
func asListServices(resp *refpb.ServerReflectionResponse) *refpb.ListServicesResponse {
if list := resp.GetListServicesResponse(); list != nil {
return list
}
if errResp := resp.GetErrorResponse(); errResp != nil {
log.Printf("reflection list failed: %s", errResp.GetErrorText())
}
return nil
} Try / catch
if list == nil {
if e := resp.GetErrorResponse(); e != nil {
return fmt.Errorf("reflection list error from server: %s", e.GetErrorText())
}
return fmt.Errorf("reflection list services returned %T", resp.MessageResponse)
} Prevention
- Handle the ErrorResponse variant explicitly instead of assuming ListServicesResponse.
- Keep server reflection implementations up to date with the protocol.
- Log unexpected %T values to diagnose proxy interference.
- Test reflection against each server version in your fleet.
When it happens
Trigger: requesting service listing via the ServerReflectionInfo stream and stream.Recv() returns a response whose GetListServicesResponse() is nil — the server answered with another message type instead of the list.
Common situations: A server behind a proxy mangling reflection responses; a server returning ErrorResponse for the LIST_SERVICES request (e.g. reflection partially disabled); version skew between reflection protocol implementations.
Related errors
- reflection lookup for %s returned %T
- connect reflected grpc target %s: %w
- reflect grpc target %s: %w
- subscriber %v takes wrong number of args: %v required signat
- subscriber %v argument type not exported: %v
AI-assisted analysis of micro/go-micro@24529f1404 (2026-09-01).
Data as JSON: /api/errors/38d909987948d804.
Report an issue: GitHub.