cfug/dio

onError not working in dio interceptor

zubair999 opened this issue · 6 comments

Package

dio

Version

5.3.3

Operating-System

Android, Windows

Output of flutter doctor -v

Doctor summary (to see all details, run flutter doctor -v):
[✓] Flutter (Channel stable, 3.16.0, on Microsoft Windows [Version 10.0.22621.2861], locale en-IN)
[✓] Windows Version (Installed version of Windows is version 10 or higher)
[✓] Android toolchain - develop for Android devices (Android SDK version 34.0.0)
[✓] Chrome - develop for the web
[✓] Visual Studio - develop Windows apps (Visual Studio Community 2022 17.8.2)
[✓] Android Studio (version 2022.2)
[✓] VS Code (version 1.85.2)
[✓] Connected device (4 available)
[✓] Network resources

• No issues found!

Dart Version

3.2.0

Steps to Reproduce

import 'dart:convert';

import 'package:dio/dio.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:realm/realm.dart';
import 'package:flutter_secure_storage/flutter_secure_storage.dart';

String appId = "someAppID";
final appConfig = AppConfiguration(appId);
final app = App(appConfig);

class DioInterceptor extends Interceptor {
  final String baseul =
      "some_base_url";
  Dio dio = Dio();
  final storage = new FlutterSecureStorage();

  @override
  Future onRequest(
      RequestOptions options, RequestInterceptorHandler handler) async {
    var accessToken = await storage.read(key: 'accessToken');
    options.baseUrl = baseul;
    options.headers.addAll({
      "Content-Type": "application/json",
      "Accept": "*/*",
    });
    if (accessToken != null && accessToken.isNotEmpty) {
      options.headers['Authorization'] = 'Bearer $accessToken';
    }
    return super.onRequest(options, handler);
  }

  @override
  void onResponse(Response response, ResponseInterceptorHandler handler) {
    return handler.next(response);
  }

  @override
  Future onError(DioError err, ErrorInterceptorHandler handler) async {
    if (err.response?.statusCode == 401) {
      await refreshToken();
      print("eroror 4011");
      try {
        return handler.resolve(await _retry(err.requestOptions));
      } on DioError catch (e) {
        handler.next(e);
      }
      return;
    }
    return handler.next(err);
    // return super.onError(err, handler);
  }

  Future<bool> refreshToken() async {
    var refreshToken = await storage.read(key: 'refreshToken');
    try {
      var response = await dio.post(
          "https://refresh-token",
          options: Options(headers: {"Authorization": refreshToken}));
      if (response.statusCode == 201) {
        await storage.write(
            key: 'accessToken',
            value: response.access_token);
      }
    } catch (e) {
      storage.deleteAll();
    }
    return true;
  }

  Future<Response<dynamic>> _retry(RequestOptions requestOptions) async {
    var accessToken = await storage.read(key: 'accessToken');
    print("on retyr========");
    print(accessToken);
    final options = Options(
      method: requestOptions.method,
      headers: {
        "Authorization": "Bearer $accessToken",
      },
    );

    print("path");
    print(requestOptions.path);
    print(requestOptions.baseUrl);

    return dio.request<dynamic>(
      requestOptions.path,
      data: requestOptions.data,
      queryParameters: requestOptions.queryParameters,
      options: options,
    );
  }
}

// final dioProvider = Provider<DioInterceptor>((ref) {
//   return DioInterceptor();
// });
1. Future<List<Data>> getUser() async {
    final dio = Dio();
    dio.interceptors.addAll([LogInterceptor(), DioInterceptor()]);

    final response = await dio.get("/getBat");
    if (response.statusCode == 200) {
      final List body = response.data['data'] as List;
      return body.map((e) => Data.fromJson(e)).toList();
    } else {
      return List.empty();
    }
  }

Expected Result

on error should run and refreshed token should work,
even if i try to print in on error nothing is printing in the console so that I come to know onError working or not

Actual Result

On error is not working as soon as request fail and 401 returned I got into dio exeptions in dio mixins

@zubair999 try to add super.onError(err, handler)

@zubair999 try to add super.onError(err, handler)

I already tried it but it 's not working. I try print in onError code block but request never there, and if reload the app then it print.

Your reproducible code is not minimal, which means hard for us to reproduce the case easily. Please consider setting breakpoints and running the app with the debugger to see it it actually works.

I have a similar problem. dio version 5.4.1

Expected Behavior:
After the request fails and triggers onError, the retried request within onError should also throw a DioException if it fails, which should then be caught by the try-catch block within the same onError method. This should allow for custom error handling or logging of the retried request failure.

Actual Behavior:
The retried request within onError triggers the onRequest interceptor again as expected, but if the retried request fails, the try-catch block within onError does not catch the subsequent DioException. This behavior prevents custom error handling for the retried request failure from being executed as intended.

Making a GET request...
onRequest is called
onError is called
onRequest is called
import 'package:dio/dio.dart';

class ErrorInterceptor extends QueuedInterceptor {
  final Dio dio;

  ErrorInterceptor(this.dio);

  @override
  Future<void> onError(
      DioException err, ErrorInterceptorHandler handler) async {
    print('onError is called');
    try {
      // This should throw an error
      await dio.fetch(err.requestOptions);
    } catch (e) {
      // Why cannot I catch the error here?
      print('onError is called again');
    }
    handler.next(err);
  }
}

class RequestInterceptor extends Interceptor {
  const RequestInterceptor();

  @override
  void onRequest(RequestOptions options, RequestInterceptorHandler handler) {
    print('onRequest is called');
    return handler.next(options);
  }
}

class ResponseIntercepter extends Interceptor {
  const ResponseIntercepter();

  @override
  void onResponse(Response response, ResponseInterceptorHandler handler) {
    print('onResponse is called');
    handler.next(response);
  }
}

void main() async {
  var dio = Dio();

  // Add the custom interceptor
  dio.interceptors.addAll([
    const RequestInterceptor(),
    const ResponseIntercepter(),
    ErrorInterceptor(dio),
  ]);

  // Making a GET request
  try {
    print('Making a GET request...');
    Response response =
        await dio.get('https://example.com/this-does-not-exist');
    print(response.data);
  } catch (e) {
    print("Final error: $e");
  }
}

Please attach more precise details so we can take further investigations. Thanks.

@AlexV525
Hi I am facing the same issue
when there is an any error like 401,404 at that time
the onError is not returning any error in inteceptors onerror code

it redirect to 

Screenshot 2024-06-26 at 4 00 18 PM

I am working with the latest version of the package