From 44f26f511edf5271f8a0eb9e0cd2ea2072741d35 Mon Sep 17 00:00:00 2001 From: LevisNgigi Date: Mon, 15 Dec 2025 15:14:42 +0300 Subject: [PATCH 1/3] fix-abort-error --- .../src/components/Chart/chartAction.js | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/superset-frontend/src/components/Chart/chartAction.js b/superset-frontend/src/components/Chart/chartAction.js index bd9bd94a56ba..dea5dc12b5f7 100644 --- a/superset-frontend/src/components/Chart/chartAction.js +++ b/superset-frontend/src/components/Chart/chartAction.js @@ -476,7 +476,17 @@ export function exploreJSON( return dispatch(chartUpdateSucceeded(queriesResponse, key)); }) .catch(response => { + // Ignore abort errors - they're expected when filters change quickly + if ( + response?.name === 'AbortError' || + response?.message === 'Request aborted' + ) { + // Abort is expected: filters changed, chart unmounted, etc. + return dispatch(chartUpdateStopped(key)); + } + if (isFeatureEnabled(FeatureFlag.GlobalAsyncQueries)) { + // In async mode we just pass the raw error response through return dispatch(chartUpdateFailed([response], key)); } @@ -494,10 +504,7 @@ export function exploreJSON( }), ); }; - if (response.name === 'AbortError') { - appendErrorLog('abort'); - return dispatch(chartUpdateStopped(key)); - } + return getClientErrorObject(response).then(parsedResponse => { if (response.statusText === 'timeout') { appendErrorLog('timeout'); From cca36b727816f6be6ee0f356b47813deae67e881 Mon Sep 17 00:00:00 2001 From: LevisNgigi Date: Wed, 17 Dec 2025 13:01:01 +0300 Subject: [PATCH 2/3] add tests --- .../src/components/Chart/chartAction.js | 7 +++--- .../src/components/Chart/chartActions.test.js | 22 +++++++++++++++++++ 2 files changed, 25 insertions(+), 4 deletions(-) diff --git a/superset-frontend/src/components/Chart/chartAction.js b/superset-frontend/src/components/Chart/chartAction.js index dea5dc12b5f7..d8ad30d79396 100644 --- a/superset-frontend/src/components/Chart/chartAction.js +++ b/superset-frontend/src/components/Chart/chartAction.js @@ -477,10 +477,9 @@ export function exploreJSON( }) .catch(response => { // Ignore abort errors - they're expected when filters change quickly - if ( - response?.name === 'AbortError' || - response?.message === 'Request aborted' - ) { + const isAbort = + response?.name === 'AbortError' || response?.statusText === 'abort'; + if (isAbort) { // Abort is expected: filters changed, chart unmounted, etc. return dispatch(chartUpdateStopped(key)); } diff --git a/superset-frontend/src/components/Chart/chartActions.test.js b/superset-frontend/src/components/Chart/chartActions.test.js index 4d57f53c2cb8..18c28de4ab01 100644 --- a/superset-frontend/src/components/Chart/chartActions.test.js +++ b/superset-frontend/src/components/Chart/chartActions.test.js @@ -357,6 +357,28 @@ describe('chart actions', () => { }); }); + test('should dispatch CHART_UPDATE_STOPPED action upon abort', () => { + fetchMock.post( + MOCK_URL, + { throws: { name: 'AbortError' } }, + { overwriteRoutes: true }, + ); + + const timeoutInSec = 100; + const actionThunk = actions.postChartFormData({}, false, timeoutInSec); + + return actionThunk(dispatch, mockGetState).then(() => { + const types = dispatch.args + .map(call => call[0] && call[0].type) + .filter(Boolean); + + expect(types).toContain(actions.CHART_UPDATE_STOPPED); + expect(types).not.toContain(actions.CHART_UPDATE_FAILED); + + setupDefaultFetchMock(); + }); + }); + test('should handle the bigint without regression', async () => { getExploreUrlStub.restore(); const mockBigIntUrl = '/mock/chart/data/bigint'; From 08e1098ed584936909f75d207a997d40c285bfd5 Mon Sep 17 00:00:00 2001 From: LevisNgigi Date: Thu, 18 Dec 2025 11:21:10 +0300 Subject: [PATCH 3/3] Trigger CI / record rebase