diff --git a/packages/grpc-js-xds/src/xds-dependency-manager.ts b/packages/grpc-js-xds/src/xds-dependency-manager.ts index 14a16c32..210cde6b 100644 --- a/packages/grpc-js-xds/src/xds-dependency-manager.ts +++ b/packages/grpc-js-xds/src/xds-dependency-manager.ts @@ -360,6 +360,10 @@ export class XdsDependencyManager { constructor(private xdsClient: XdsClient, private listenerResourceName: string, private dataPlaneAuthority: string, private watcher: XdsConfigWatcher) { this.ldsWatcher = new Watcher({ onResourceChanged: (update: Listener__Output) => { + if (!update.api_listener) { + this.trace('Received Listener resource not usable on client'); + return; + } this.latestListener = update; const httpConnectionManager = decodeSingleResource(HTTP_CONNECTION_MANGER_TYPE_URL, update.api_listener!.api_listener!.value); switch (httpConnectionManager.route_specifier) { diff --git a/packages/grpc-js-xds/src/xds-resource-type/listener-resource-type.ts b/packages/grpc-js-xds/src/xds-resource-type/listener-resource-type.ts index f78bc7e6..82586fe4 100644 --- a/packages/grpc-js-xds/src/xds-resource-type/listener-resource-type.ts +++ b/packages/grpc-js-xds/src/xds-resource-type/listener-resource-type.ts @@ -294,6 +294,9 @@ export class ListenerResourceType extends XdsResourceType { if (message.default_filter_chain) { errors.push(...validateFilterChain(context, message.default_filter_chain).map(error => `default_filter_chain: ${error}`)); } + if (!message.api_listener && !message.default_filter_chain && message.filter_chains.length === 0) { + errors.push('No api_listener and no filter_chains and no default_filter_chain'); + } if (errors.length === 0) { return { valid: true,