Skip to content

fix(dio): support classes that implement Interceptor - #2591

Open
AlexV525 wants to merge 1 commit into
mainfrom
fix/2590-interceptor-implements
Open

fix(dio): support classes that implement Interceptor#2591
AlexV525 wants to merge 1 commit into
mainfrom
fix/2590-interceptor-implements

Conversation

@AlexV525

Copy link
Copy Markdown
Member

Closes #2590

Problem

NoSuchMethodError: Class 'X' has no instance method '_invokeError' at runtime when a class uses implements Interceptor instead of extends Interceptor.

PR #2567 added private instance methods (_invokeRequest, _invokeResponse, _invokeError) on Interceptor and dispatched the interceptor pipeline through them. These methods exist only via inheritance — a class that implements Interceptor provides the public onRequest/onResponse/onError methods but does not inherit the private ones, so the pipeline crashes at runtime.

This is a behavioral regression introduced in 5.11.0 (the release that shipped #2567).

Fix

Move the dynamic-dispatch mechanism from private instance methods on Interceptor to a top-level helper function _invokeCallbackDynamically, and call it via closures at each dispatch site (DioMixin.fetch and QueuedInterceptor._handle*). The pipeline now references exclusively the public onRequest/onResponse/onError methods. Both extends Interceptor and implements Interceptor work.

The dynamic invocation is preserved: a Future<void> returned by an async override of a void method is still captured at runtime so _observeInterceptorCallback can observe asynchronous errors — the original motivation from #2567.

Why a top-level function instead of private instance methods?

Private instance methods are not part of the interface contract. Any class using implements Interceptor would not inherit them. A top-level function that takes the public method as a parameter keeps dispatch through the public API surface only. The Interceptor class doc comment now documents this dispatch contract.

Compatibility

  • No public API change: no signature change, no symbol added/removed, no typedef change.
  • No SDK lower-bound increase.
  • No behavior change for extends Interceptor, InterceptorsWrapper, QueuedInterceptor, or QueuedInterceptorsWrapper.
  • The fix restores 5.10 behavior for implements Interceptor users.

Verification

Added 3 regression tests covering implements Interceptor:

  • Synchronous callbacks through request → response stages.
  • Error stage reached on a failing response (404).
  • Async onRequest override that throws — dynamic dispatch captures the Future, observer rejects the handler.

dart analyze --fatal-infos clean. 55 tests pass across interceptor_test.dart and queued_interceptor_test.dart (including the existing #2565 deduplication regression test, all #2499 async-hang tests, and wrapper-subclass override tests). Broader non-network suite (dio_mixin_test, cancel_token_test, exception_test): 68 passed, 1 skipped (TLS).

Unverified: Web platform (Chrome/Firefox) not run locally — dynamic dispatch is a Dart language-spec guarantee, not a VM optimization, and the same pattern has been used in _InterceptorWrapperMixin since #2567.

AI Attribution

Implementation, tests, and analysis by GLM-5.2.

PR #2567 introduced private instance methods (_invokeRequest,
_invokeResponse, _invokeError) on Interceptor and dispatched the
pipeline through them. Classes using `implements Interceptor` do not
inherit private methods, causing NoSuchMethodError at runtime (#2590).

Move dynamic dispatch to a top-level _invokeCallbackDynamically helper
and call it via closures at each dispatch site. The pipeline now
references only the public onRequest/onResponse/onError methods, so
both `extends Interceptor` and `implements Interceptor` work.

Added regression tests for synchronous and async `implements
Interceptor` usage across all three interceptor stages.

Co-Authored-By: GLM-5.2 <noreply@zhipu.ai>
@AlexV525
AlexV525 requested a review from a team as a code owner August 14, 2026 03:57
@AlexV525

This comment was marked as duplicate.

@AlexV525

Copy link
Copy Markdown
Member Author

(Workflows are failing because of flutter/flutter#191056)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Breaking change is not documented: NoSuchMethodError: Class X has no instance method '_invokeError'.

1 participant