grpc/grpc-go · error
unexpected message type %T
Error message
unexpected message type %T
What it means
Returned by adsStreamImpl.recvMessage when stream.Recv() succeeds but the bytes cannot be unmarshaled into envoy.service.discovery.v3.DiscoveryResponse. recv() then reports the error via onError (which sets streamEstablished=false after the first failure) and closes the stream; the runner re-runs with backoff if no message was ever received.
Source
Thrown at internal/xds/clients/xdsclient/ads_stream.go:495
// know that it's invalid. But we shouldn't ACK either, because we
// don't know that it is valid.
s.logger.Warningf("%v", nackErr)
continue
}
s.onRecv(stream, resourceNames, url, version, nonce, nackErr)
}
}
func (s *adsStreamImpl) recvMessage(stream clients.Stream) (resources []*anypb.Any, url, version, nonce string, err error) {
r, err := stream.Recv()
if err != nil {
return nil, "", "", "", err
}
var resp v3discoverypb.DiscoveryResponse
if err := proto.Unmarshal(r, &resp); err != nil {
s.logger.Infof("Failed to unmarshal response to DiscoveryResponse: %v", err)
return nil, "", "", "", fmt.Errorf("unexpected message type %T", r)
}
if s.logger.V(perRPCVerbosityLevel) {
s.logger.Infof("ADS response received: %v", pretty.ToJSON(&resp))
} else if s.logger.V(2) {
s.logger.Infof("ADS response received for type %q, version %q, nonce %q", resp.GetTypeUrl(), resp.GetVersionInfo(), resp.GetNonce())
}
return resp.GetResources(), resp.GetTypeUrl(), resp.GetVersionInfo(), resp.GetNonce(), nil
}
// onRecv is invoked when a response is received from the server. The arguments
// passed to this method correspond to the most recently received response.
//
// It performs the following actions:
// - updates resource type specific state
// - updates resource specific state for resources in the response
// - sends an ACK or NACK to the server based on the response
func (s *adsStreamImpl) onRecv(stream clients.Stream, names []string, url, version, nonce string, nackErr error) {
s.mu.Lock()View on GitHub (pinned to 03255a9237)
Solutions
- Confirm the server implements the v3 AggregatedDiscoveryService and that the client and server agree on the xDS major version.
- Use grpcurl to call StreamAggregatedResources and verify the returned bytes unmarshal as DiscoveryResponse.
- Remove any intermediating proxy that may rewrite the body.
- Upgrade/align go-control-plane and grpc-go versions on client and server.
Defensive patterns
Strategy: validation
Prevention
- Use a v3-conformant ADS management server.
- Keep grpc-go/go-control-plane versions aligned between client and server.
- Do not place a body-rewriting proxy in front of the ADS endpoint.
When it happens
Trigger: The ADS management server sends a message on '/envoy.service.discovery.v3.AggregatedDiscoveryService/StreamAggregatedResources' that is not a valid DiscoveryResponse protobuf — e.g. a v2 DiscoveryResponse, an HTML/proxy error body, or a garbage frame.
Common situations: Version skew between client (v3) and server (v2), a non-xDS service behind the same URI, a proxy/LB corrupting the HTTP/2 body, or an in-progress server upgrade emitting a transient malformed frame.
Related errors
- lrs: unexpected message type %T
- recovered from panic during resource parsing, resource: %v,
- xds: failed to create transport for server config %v: %v
- rls_csp: error parsing config %v: %v
- rls_csp: error marshaling route lookup config: %v: %v
AI-assisted analysis of grpc/grpc-go@03255a9237 (2026-08-07).
Data as JSON: /api/errors/de936816f646bb8b.
Report an issue: GitHub.