'Flutter : Handling error Dio Package (404,400 etc)
I'm learn searching data by ID with package DIO https://pub.dev/packages/dio, my problem is every time I'm type wrong keyword search, the app suddenly crash with debug message 404 Not Found.
I know data not found because I'm type wrong keyword, but I'm already handle this with this code
Widget _searchKeywordMahasiswa() {
return FutureBuilder<List<Mosque>>(
future: api.getMahasiswaById(_searchText),
builder: (BuildContext context, AsyncSnapshot snapshot) {
if (snapshot.hasData) {
return Expanded(
child: ListView.builder(
shrinkWrap: true,
itemCount: snapshot.data.length,
itemBuilder: (BuildContext context, int index) {
return Text(snapshot.data[index].id);
},
),
);
} else if (!snapshot.data) { <<<<<< IN THIS LINE
return Center(
child: Icon(
Icons.sentiment_very_dissatisfied,
size: 150.0,
),
);
}
return CircularProgressIndicator();
},
);
// return CircularProgressIndicator();
}
Future<List<Mosque>> getMahasiswaById(String id) async{
try {
var apiRespon = await dio.get('${Urls.BASE_API_URL}/mahasiswa/get/id/$id');
var apiResponJson = apiRespon.data;
print(apiResponJson);
return (apiResponJson['data'] as List).map((p)=>Mosque.fromJson(p)).toList();
}on DioError catch (e) { <<<<< IN THIS LINE
if(e.response.statusCode == 404){
print(e.response.statusCode);
}else{
print(e.message);
print(e.request);
}
}
}
In same case my App crash too if i'm get error 400 Bad Request And i'm already handle this error but not works.
Can you Help Me With This?
Solution 1:[1]
var response = await dio.delete(
url,
data: postData,
options: Options(
followRedirects: false,
validateStatus: (status) {
return status < 500;
},
headers: headers,
),
);
please use the code below bro,
add followRedirects, validateStatus to your code.
Solution 2:[2]
remove 'on DioError' - unfortunately there are some errors (404's, 500s...) that Dio wont't process and won't catch - had similar problem in my app. Then change code to posted below or use some other logic to 'catch'em all' ;)
} catch (e) {
if (e is DioError) {
//handle DioError here by error type or by error code
} else {
...
}
//return empty list (you can also return custom error to be handled by Future Builder)
}
by the way you should properly handle Future Builder states: snapshot.hasData
, empty data and snapshot.hasError
in your future builder to prevent future crashes
Solution 3:[3]
Error is with this URL string pattern ${Urls.BASE_API_URL}/mahasiswa/get/id/$id
you can not use . operator and access the inner value from any object inside "". You can store the exact url in other variable and use it in that line. Code should be as follows.
Future<List<Mosque>> getMahasiswaById(String id) async{
try {
var baseURL = Urls.BASE_API_URL;
var apiRespon = await dio.get('${baseURL}/mahasiswa/get/id/$id');
var apiResponJson = apiRespon.data;
print(apiResponJson);
return (apiResponJson['data'] as List).map((p)=>Mosque.fromJson(p)).toList();
}on DioError catch (e) { <<<<< IN THIS LINE
if(e.response.statusCode == 404){
print(e.response.statusCode);
}else{
print(e.message);
print(e.request);
}
}
}
============ UPDATE ============
You can use .
operator as follows,
var apiRespon = await dio.get('${Urls.BASE_API_URL}/mahasiswa/get/id/$id');
Solution 4:[4]
I had the same problem it was just changing my interceptor that worked
import 'package:dio/dio.dart';
class CustomInterceptor extends Interceptor {
@override
void onRequest(RequestOptions options, RequestInterceptorHandler handler) async {
print("onRequest");
return super.onRequest(options, handler);
}
@override
Future onResponse(Response response, ResponseInterceptorHandler handler) {
print("onResponse");
return null;
}
@override
Future onError(DioError err, ErrorInterceptorHandler handler) async {
print("onError: ${err.response.statusCode}");
return handler.next(err); // <--- THE TIP IS HERE
}
}
Solution 5:[5]
You can manage timeout exception using DioClient
:
There are two way, declaring customized Option
then assign to the Dio
or directly assign below option
to it, but I prefer to separate these type of Option
for oriented need.
You can set a condition to get all problems except 400 (success) response, but you have to aware of Connection Timeout, so here a integrated in Dio way:
class YourRepositary {
Dio dioClient;
YourRepositary() {
if (dioClient == null) {
BaseOptions options = new BaseOptions(
baseUrl: "YOUR_APIs_BASE_URL",
receiveDataWhenStatusError: true,
connectTimeout: 30000, // 30 seconds
receiveTimeout: 30000 // 30 seconds
);
dioClient = new Dio(options);
}
}
Future<ProductResponseModel> getProduct(var productRequestInputDto) async {
try {
Response response = await dio.post("/api/getProduct", data: productRequestInputDto);
final ProductResponseModel _productModel = ProductResponseModel.fromJson(response.data);
return _productModel ;
} on DioError catch (ex) {
if(ex.type == DioErrorType.CONNECT_TIMEOUT){
throw Exception("Connection Timeout Exception");
}
throw Exception(ex.message);
}
}
}
At the end, below example demonstrate how you handle Timeout exception or even handled by your backend 500 error in API call:
void getProduct(){
ProductRequestInputDto productRequest = new ProductRequestInputDto(productId: "666");
var requestBody = jsonEncode(loginRequest);
debugPrint("Request Data : $requestBody");
_apiRepositary.getProduct(requestBody).then((response){
debugPrint("Login Success $response");
//manage your response here
},
onError: (exception){
//Handle exception message
if(exception.message != null ){
debugPrint(exception.message); // Here you get : "Connection Timeout Exception" or even handled 500 errors on your backend.
}
},
);
}
To conclusion, it's all about receiveDataWhenStatusError: true
, in the option of Dio.
Solution 6:[6]
I also had the similar type problem.
First, try to run the project from command prompt with flutter run
see if there is occurring any problem or not.
If the command prompt is showing no problem & your app is running smoothly then you have to check the IDE. If you are using VSCode then switch to Debug is side bar, see which options are ticked in Breakpoint section. If All Exceptions
is ticked then the debugger will pause on every exception. Uncheck both All Exceptions
& Uncaught Exceptions
then try refresh restart.
Hope this will solve your problem.
Solution 7:[7]
Found a solution. This code worked for me.
try {
Dio dio = Dio();
var res = await dio.download(
url + 'fg',
savePath.path + "/filename.bin",
onReceiveProgress: (count, total) {
progress(count, total);
},
);
} on DioError catch (e) {
if (e.type == DioErrorType.response) {
print('catched');
return;
}
if (e.type == DioErrorType.connectTimeout) {
print('check your connection');
return;
}
if (e.type == DioErrorType.receiveTimeout) {
print('unable to connect to the server');
return;
}
if (e.type == DioErrorType.other) {
print('Something went wrong');
return;
}
print(e);
} catch (e) {
print(e);
}
Solution 8:[8]
dynamic _decodeErrorResponse(dynamic e) {
dynamic data = {"statusCode": -1, "message": "Unknown Error"};
if (e is DioError) {
if (e.type == DioErrorType.response) {
final response = e.response;
try {
if (response != null && response.data != null) {
final Map responseData =
json.decode(response.data as String) as Map;
data["message"] = responseData['message'] as String;
data["statusCode"] = response.statusCode;
}
} catch (e) {
data["message"] = "Internal Error Catch";
}
} else if (e.type == DioErrorType.connectTimeout ||
e.type == DioErrorType.receiveTimeout ||
e.type == DioErrorType.sendTimeout) {
data["message"] = "Request timeout";
data["statusCode"] = 408;
} else if (e.error is SocketException) {
data["message"] = "No Internet Connection!";
}
}
return data;
}
Solution 9:[9]
The selected answer is working perfectly fine. But if someone still getting an error after adding those lines. You can try this one.
Add content type to the field.
dio.FormData formData = dio.FormData.fromMap({
"file": await dio.MultipartFile.fromFile(
file.path,
filename: fileName,
contentType: MediaType('audio', 'mp4'),
),
Solution 10:[10]
I had the same issue, and this is how I solved it.
} catch (exception) {
if (exception.runtimeType == DioError) {
var dioException = exception as DioError;
return dioException.response!; // Do something with response
}
rethrow; // or do something else with response
}
}
It's similar to some of the answers above, but I had to use if(exception.runtimeType == DioError)
to check the type of the exception, as if(exception is DioError)
didn't seem to work for me.
Hope it helps someone.
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
Solution | Source |
---|---|
Solution 1 | Daanzel |
Solution 2 | |
Solution 3 | |
Solution 4 | Claudney Sessa |
Solution 5 | |
Solution 6 | |
Solution 7 | MBK |
Solution 8 | Arun NS |
Solution 9 | MBK |
Solution 10 | Steven Armoo |