From 29d09eadf2163599617dfd904f62e26af9c4890a Mon Sep 17 00:00:00 2001 From: khanhx Date: Wed, 3 Jun 2026 19:29:50 +0700 Subject: [PATCH] fix(messages): prevent invalid JSONPath preview filter from crashing the page --- .../Topics/Topic/Messages/Message.tsx | 17 +++++++++++++---- .../Topic/Messages/__test__/Message.spec.tsx | 9 +++++++++ 2 files changed, 22 insertions(+), 4 deletions(-) diff --git a/frontend/src/components/Topics/Topic/Messages/Message.tsx b/frontend/src/components/Topics/Topic/Messages/Message.tsx index d3cf4d47c6..636a64aa78 100644 --- a/frontend/src/components/Topics/Topic/Messages/Message.tsx +++ b/frontend/src/components/Topics/Topic/Messages/Message.tsx @@ -80,6 +80,18 @@ const Message: React.FC = ({ message, keyFilters, contentFilters }) => { } }; + const evaluateFilter = (path: string, json: unknown) => { + // A stored preview filter can hold an invalid JSONPath (e.g. saved before + // validation existed, or one that only throws against real message data). + // Evaluating it during render would otherwise throw and crash the whole + // messages page on every load until local storage is cleared manually. + try { + return JSON.stringify(JSONPath({ path, json, wrap: false })); + } catch { + return 'Invalid JSONPath'; + } + }; + const renderFilteredJson = ( jsonValue?: string, filters?: PreviewFilter[] @@ -92,10 +104,7 @@ const Message: React.FC = ({ message, keyFilters, contentFilters }) => { {filters.map((item) => { return (
- {item.field}:{' '} - {JSON.stringify( - JSONPath({ path: item.path, json: parsedJson, wrap: false }) - )} + {item.field}: {evaluateFilter(item.path, parsedJson)}
); })} diff --git a/frontend/src/components/Topics/Topic/Messages/__test__/Message.spec.tsx b/frontend/src/components/Topics/Topic/Messages/__test__/Message.spec.tsx index 90825cb28c..fa822865e6 100644 --- a/frontend/src/components/Topics/Topic/Messages/__test__/Message.spec.tsx +++ b/frontend/src/components/Topics/Topic/Messages/__test__/Message.spec.tsx @@ -176,6 +176,15 @@ describe('Message component', () => { expect(keyFiltered).toBeInTheDocument(); }); + it('does not crash the row when a preview filter has an invalid JSONPath', () => { + const props = { + message: { ...mockMessage, value: mockMessageValue as string }, + contentFilters: [{ field: 'broken', path: '$[?(@.foo.bar.baz)]' }], + }; + renderComponent(props); + expect(screen.getByText('broken: Invalid JSONPath')).toBeInTheDocument(); + }); + it('shows action options in dropdown on click', async () => { renderComponent(); const trElement = screen.getByRole('row');