From 236d220d61a28dc2b4455c4a0434a64cba1be666 Mon Sep 17 00:00:00 2001 From: Alex Li Date: Sat, 27 Jun 2026 10:13:26 +0800 Subject: [PATCH 1/3] fix: add callFollowingErrorInterceptor to ErrorInterceptorHandler.reject RequestInterceptorHandler and ResponseInterceptorHandler both support the callFollowingErrorInterceptor flag in their reject() methods, but ErrorInterceptorHandler.reject() was missing it, always emitting InterceptorResultType.reject and causing subsequent error interceptors to be skipped unconditionally. The errorInterceptorWrapper in dio_mixin.dart already handles rejectCallFollowing correctly, so only the handler method needed fixing. Fixes #2462 Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- dio/lib/src/interceptor.dart | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/dio/lib/src/interceptor.dart b/dio/lib/src/interceptor.dart index ad9feb278..4e12dc8b8 100644 --- a/dio/lib/src/interceptor.dart +++ b/dio/lib/src/interceptor.dart @@ -178,10 +178,24 @@ class ErrorInterceptorHandler extends _BaseHandler { } /// Completes the request by reject with the [error] as the result. - void reject(DioException error) { + /// + /// Invoking the method will make the rest of interceptors in the queue + /// skipped to handle the request, + /// unless [callFollowingErrorInterceptor] is true + /// which delivers [InterceptorResultType.rejectCallFollowing] + /// to the [InterceptorState]. + void reject( + DioException error, [ + bool callFollowingErrorInterceptor = false, + ]) { _throwIfCompleted(); _completer.completeError( - InterceptorState(error, InterceptorResultType.reject), + InterceptorState( + error, + callFollowingErrorInterceptor + ? InterceptorResultType.rejectCallFollowing + : InterceptorResultType.reject, + ), error.stackTrace, ); _processNextInQueue?.call(); From ce20f1ffc84a399d103688cb4724e1ac366fd03a Mon Sep 17 00:00:00 2001 From: Alex Li Date: Sat, 27 Jun 2026 10:39:54 +0800 Subject: [PATCH 2/3] test: cover reject callFollowing in queued error interceptors Add a regression test to ensure calling ErrorInterceptorHandler.reject(error, true) inside QueuedInterceptorsWrapper continues to following error interceptors. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- dio/test/interceptor_test.dart | 33 +++++++++++++++++++++++++++++++++ 1 file changed, 33 insertions(+) diff --git a/dio/test/interceptor_test.dart b/dio/test/interceptor_test.dart index 6237975dd..8ffc88b38 100644 --- a/dio/test/interceptor_test.dart +++ b/dio/test/interceptor_test.dart @@ -844,6 +844,39 @@ void main() { expect(tokenRequestCounts, 1); expect(result, 3); }); + + test( + 'error interceptor reject with callFollowingErrorInterceptor continues', + () async { + final dio = Dio() + ..options.baseUrl = MockAdapter.mockBase + ..httpClientAdapter = MockAdapter(); + + dio.interceptors + ..add( + QueuedInterceptorsWrapper( + onError: (error, handler) { + handler.reject(error.copyWith(error: 1), true); + }, + ), + ) + ..add( + QueuedInterceptorsWrapper( + onError: (error, handler) { + final count = error.error as int; + handler.next(error.copyWith(error: count + 1)); + }, + ), + ); + + expect( + dio + .get('/test-not-found') + .catchError((e) => throw (e as DioException).error as int), + throwsA(2), + ); + }, + ); }); group('LogInterceptor', () { From 9ec9ac9751faf961d2ee86ada3dba5446bcf2794 Mon Sep 17 00:00:00 2001 From: Alex Li Date: Sun, 28 Jun 2026 20:37:48 +0800 Subject: [PATCH 3/3] docs: add changelog for queued interceptor reject fix --- dio/CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/dio/CHANGELOG.md b/dio/CHANGELOG.md index 276a68eeb..78e72a7aa 100644 --- a/dio/CHANGELOG.md +++ b/dio/CHANGELOG.md @@ -11,6 +11,7 @@ See the [Migration Guide][] for the complete breaking changes list.** On web, timeout handling is best-effort because synchronous JavaScript work cannot be preempted. - Fix `FormData.clone()` dropping `boundaryName` and `camelCaseContentDisposition`, so a retried multipart request now keeps the original options instead of silently falling back to the defaults. - Fix `QueuedInterceptor` stalling its queue forever when the active request is cancelled while its callback is still pending (never calls `next`/`resolve`/`reject`), which blocked every subsequent request routed through the interceptor. +- Fix `ErrorInterceptorHandler.reject(..., true)` not continuing to following error interceptors in queued interceptors. ## 5.9.2