From c8b4202b890af585b434428ca87c0633b96b23cc Mon Sep 17 00:00:00 2001 From: Warren Lee <5959690+wrn14897@users.noreply.github.com> Date: Wed, 9 Sep 2026 22:04:27 -0700 Subject: [PATCH] fix(llm): keep a scope select clearable when its options fail to load MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Pinning the applied value made it visible, but the control was still disabled on isLoading || isError — so a failing distinct-value query left the user looking at a filter they could not remove, permanently. Only disable when nothing is applied. --- .changeset/quiet-pugs-clap.md | 11 +++++++ .../__tests__/DistinctValueSelect.test.tsx | 32 ++++++++++++++++++- .../src/llm/dashboard/DistinctValueSelect.tsx | 5 ++- 3 files changed, 46 insertions(+), 2 deletions(-) create mode 100644 .changeset/quiet-pugs-clap.md diff --git a/.changeset/quiet-pugs-clap.md b/.changeset/quiet-pugs-clap.md new file mode 100644 index 0000000000..733a6f7d9b --- /dev/null +++ b/.changeset/quiet-pugs-clap.md @@ -0,0 +1,11 @@ +--- +'@hyperdx/app': patch +--- + +fix: keep the LLM dashboard scope filters clearable when their options fail to +load + +The session and user dropdowns were disabled whenever their distinct-value query +was loading or had failed. With a filter applied that left the user looking at a +scope they could see but could not remove — permanently, if the query kept +failing. They now stay interactive whenever a value is applied. diff --git a/packages/app/src/llm/__tests__/DistinctValueSelect.test.tsx b/packages/app/src/llm/__tests__/DistinctValueSelect.test.tsx index 8565aaf639..57647a9028 100644 --- a/packages/app/src/llm/__tests__/DistinctValueSelect.test.tsx +++ b/packages/app/src/llm/__tests__/DistinctValueSelect.test.tsx @@ -5,11 +5,12 @@ import { DistinctValueSelect } from '@/llm/dashboard/DistinctValueSelect'; let mockRows: Record[] | undefined = []; let mockLoading = false; +let mockError = false; jest.mock('@/hooks/useChartConfig', () => ({ useQueriedChartConfig: () => ({ data: mockRows == null ? undefined : { data: mockRows }, isLoading: mockLoading, - isError: false, + isError: mockError, }), })); @@ -28,6 +29,7 @@ describe('DistinctValueSelect', () => { beforeEach(() => { mockRows = []; mockLoading = false; + mockError = false; }); it('shows the applied value when it is present in the fetched options', () => { @@ -83,6 +85,34 @@ describe('DistinctValueSelect', () => { expect(onChange).not.toHaveBeenCalled(); }); + // Otherwise a failing distinct query strands the user with a filter they + // can see but cannot remove. + it('stays interactive while a value is applied even if the query fails', () => { + mockRows = undefined; + mockError = true; + renderWithMantine( + , + ); + + const input = screen.getByRole('combobox'); + expect(input).toHaveValue('alice@x.com'); + expect(input).not.toBeDisabled(); + }); + + it('disables the control while loading with nothing applied', () => { + mockRows = undefined; + mockLoading = true; + renderWithMantine( + , + ); + + expect(screen.getByRole('combobox')).toBeDisabled(); + }); + it('falls back to the placeholder when no value is applied', () => { mockRows = [{ value: 'bob@x.com' }]; renderWithMantine( diff --git a/packages/app/src/llm/dashboard/DistinctValueSelect.tsx b/packages/app/src/llm/dashboard/DistinctValueSelect.tsx index fe947d79b0..c760aa608e 100644 --- a/packages/app/src/llm/dashboard/DistinctValueSelect.tsx +++ b/packages/app/src/llm/dashboard/DistinctValueSelect.tsx @@ -89,7 +89,10 @@ export function DistinctValueSelect({ data={values} value={value || null} onChange={v => onChange(v ?? '')} - disabled={isLoading || isError} + // Never lock the control while a scope is applied: the options are of no + // use yet, but clearing the filter must stay possible. On a failing + // distinct query that is otherwise permanent. + disabled={(isLoading || isError) && !value} comboboxProps={{ withinPortal: false }} searchable clearable