diff --git a/x-pack/plugins/lens/public/indexpattern_datasource/datapanel.test.tsx b/x-pack/plugins/lens/public/indexpattern_datasource/datapanel.test.tsx index 0d60bd588f71..4a79f30a17a0 100644 --- a/x-pack/plugins/lens/public/indexpattern_datasource/datapanel.test.tsx +++ b/x-pack/plugins/lens/public/indexpattern_datasource/datapanel.test.tsx @@ -324,8 +324,11 @@ describe('IndexPattern Data Panel', () => { }; } - async function testExistenceLoading(stateChanges?: unknown, propChanges?: unknown) { - const props = testProps(); + async function testExistenceLoading( + stateChanges?: unknown, + propChanges?: unknown, + props = testProps() + ) { const inst = mountWithIntl(); await act(async () => { @@ -536,6 +539,25 @@ describe('IndexPattern Data Panel', () => { expect(core.http.post).toHaveBeenCalledTimes(2); expect(overlapCount).toEqual(0); }); + + it("should default to empty dsl if query can't be parsed", async () => { + const props = { + ...testProps(), + query: { + language: 'kuery', + query: '@timestamp : NOT *', + }, + }; + await testExistenceLoading(undefined, undefined, props); + + expect((props.core.http.post as jest.Mock).mock.calls[0][1].body).toContain( + JSON.stringify({ + must_not: { + match_all: {}, + }, + }) + ); + }); }); describe('displaying field list', () => { diff --git a/x-pack/plugins/lens/public/indexpattern_datasource/datapanel.tsx b/x-pack/plugins/lens/public/indexpattern_datasource/datapanel.tsx index eb7940634d78..91c068c2b4fa 100644 --- a/x-pack/plugins/lens/public/indexpattern_datasource/datapanel.tsx +++ b/x-pack/plugins/lens/public/indexpattern_datasource/datapanel.tsx @@ -22,7 +22,7 @@ import { } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; import { FormattedMessage } from '@kbn/i18n/react'; -import { DataPublicPluginStart } from 'src/plugins/data/public'; +import { DataPublicPluginStart, EsQueryConfig, Query, Filter } from 'src/plugins/data/public'; import { DatasourceDataPanelProps, DataType, StateSetter } from '../types'; import { ChildDragDropProvider, DragContextState } from '../drag_drop'; import { FieldItem } from './field_item'; @@ -74,6 +74,27 @@ const fieldTypeNames: Record = { ip: i18n.translate('xpack.lens.datatypes.ipAddress', { defaultMessage: 'IP' }), }; +// Wrapper around esQuery.buildEsQuery, handling errors (e.g. because a query can't be parsed) by +// returning a query dsl object not matching anything +function buildSafeEsQuery( + indexPattern: IIndexPattern, + query: Query, + filters: Filter[], + queryConfig: EsQueryConfig +) { + try { + return esQuery.buildEsQuery(indexPattern, query, filters, queryConfig); + } catch (e) { + return { + bool: { + must_not: { + match_all: {}, + }, + }, + }; + } +} + export function IndexPatternDataPanel({ setState, state, @@ -106,7 +127,7 @@ export function IndexPatternDataPanel({ timeFieldName: indexPatterns[id].timeFieldName, })); - const dslQuery = esQuery.buildEsQuery( + const dslQuery = buildSafeEsQuery( indexPatterns[currentIndexPatternId] as IIndexPattern, query, filters, diff --git a/x-pack/plugins/lens/public/indexpattern_datasource/field_item.tsx b/x-pack/plugins/lens/public/indexpattern_datasource/field_item.tsx index 815725f4331a..fabf9e9e9bff 100644 --- a/x-pack/plugins/lens/public/indexpattern_datasource/field_item.tsx +++ b/x-pack/plugins/lens/public/indexpattern_datasource/field_item.tsx @@ -198,10 +198,12 @@ export const InnerFieldItem = function InnerFieldItem(props: FieldItemProps) { className={`lnsFieldItem__info ${infoIsOpen ? 'lnsFieldItem__info-isOpen' : ''}`} data-test-subj={`lnsFieldListPanelField-${field.name}`} onClick={() => { - togglePopover(); + if (exists) { + togglePopover(); + } }} onKeyPress={(event) => { - if (event.key === 'ENTER') { + if (exists && event.key === 'ENTER') { togglePopover(); } }}