http icon indicating copy to clipboard operation
http copied to clipboard

Flutter try catch can't catch SocketException ( Exception has occurred. SocketException (SocketException: OS Error: No route to host, errno = 113)

Open sujith2014 opened this issue 3 years ago • 33 comments

Flutter App crashed after getting this exception

Exception has occurred. SocketException (SocketException: OS Error: No route to host, errno = 113, address = 10.162.18.32, port = 60208)

THE same URL is accessible from the testing phone, Postman. also tried with

try {

} on SocketException {

}

Still, Exception is not handled.

 
 Future<List<Post>> getPosts() async {
    final prefs = await SharedPreferences.getInstance();
    final key = 'token';
    print(prefs.get(key));
    final value = prefs.get(key) ?? 0;
    Map<String, String> headers = {
      "Accept": "application/json",
      "Authorization": "Bearer $value"
    };
    print("before res");
    var responseJson;
    try {
      print("ins try get url " + host + "posts");
      final response = await http.get(host + "posts",
          headers: headers);   //Exception on this line
      print("final try");
      responseJson = _response(response);
    } catch (e) {
      print(e);
      return null;
      //throw FetchDataException('No Internet connection');
    }
    // if (res.statusCode == 200) {
    List<dynamic> body = responseJson;

    List<Post> posts = body
        .map(
          (dynamic item) => Post.fromJson(item),
        )
        .toList();

    return posts;
    // } else {
    //   print('A network error occurred');
    //   //throw "Can't get posts.";
    // }
  }

flutter doctor

Doctor summary (to see all details, run flutter doctor -v):
[√] Flutter (Channel stable, 2.0.2, on Microsoft Windows [Version 10.0.18363.836], locale en-US)
[√] Android toolchain - develop for Android devices (Android SDK version 30.0.1)
[√] Chrome - develop for the web
[√] Android Studio (version 4.1.0)
[√] VS Code (version 1.54.3)
[√] Connected device (2 available)

• No issues found!
PS C:\Users\nicalp\AndroidStudioProjects\vikasapp> flutter --version
Flutter 2.0.2 • channel stable • https://github.com/flutter/flutter.git
Framework • revision 8962f6dc68 (11 days ago) • 2021-03-11 13:22:20 -0800
Engine • revision 5d8bf811b3

Screenshots

https://i.ibb.co/VVHV3Sr/image.png

https://i.ibb.co/GMRZZ21/image.png

sujith2014 avatar Mar 23 '21 04:03 sujith2014

same here: flutter: SocketException: Connection failed (OS Error: Network is unreachable, errno = 51), address = 192.168.4.1, port = 80 though it's accessible from my phone's google chrome.

[✓] Flutter (Channel master, 2.1.0-13.0.pre.294, on macOS 11.2.3 20D91 darwin-x64, locale en)
    • Flutter version 2.1.0-13.0.pre.294 at /Users/shalaby/Developer/flutter
    • Framework revision a603714610 (25 hours ago), 2021-03-28 03:54:02 -0700
    • Engine revision b5e15d055d
    • Dart version 2.13.0 (build 2.13.0-162.0.dev)

[✓] Android toolchain - develop for Android devices (Android SDK version 30.0.3)
    • Android SDK at /Users/shalaby/Library/Android/sdk
    • Platform android-30, build-tools 30.0.3
    • Java binary at: /Applications/Android Studio.app/Contents/jre/jdk/Contents/Home/bin/java
    • Java version OpenJDK Runtime Environment (build 1.8.0_242-release-1644-b3-6915495)
    • All Android licenses accepted.

[✓] Xcode - develop for iOS and macOS
    • Xcode at /Applications/Xcode.app/Contents/Developer
    • Xcode 12.4, Build version 12D4e
    • CocoaPods version 1.10.1

[✓] Chrome - develop for the web
    • Chrome at /Applications/Google Chrome.app/Contents/MacOS/Google Chrome

[✓] Android Studio (version 4.1)
    • Android Studio at /Applications/Android Studio.app/Contents
    • Flutter plugin can be installed from:
      🔨 https://plugins.jetbrains.com/plugin/9212-flutter
    • Dart plugin can be installed from:
      🔨 https://plugins.jetbrains.com/plugin/6351-dart
    • Java version OpenJDK Runtime Environment (build 1.8.0_242-release-1644-b3-6915495)

[✓] VS Code (version 1.54.3)
    • VS Code at /Applications/Visual Studio Code.app/Contents
    • Flutter extension version 3.20.0

[✓] Connected device (2 available)
    • Mahmoud’s iPhone (mobile) • 00008030-00037981012A802E • ios            • iOS 14.4.2
    • Chrome (web)              • chrome                    • web-javascript • Google Chrome 89.0.4389.90

• No issues found!

tested on stable, dev, and master channels. using latest package release

EgHubs avatar Mar 29 '21 12:03 EgHubs

I also had a similar problem in case the server still hasn't started. App crash right at this line of code

例外が発生しました
SocketException (SocketException: OS Error: Connection refused, errno = 111, address = 192.168.xxx.xxx, port = xxx)
flutter doctor 
[✓] Flutter (Channel stable, 2.0.3, on macOS 11.2.3 20D91 darwin-x64, locale ja-JP)
    • Flutter version 2.0.3 at $HOME/develop/flutter
    • Framework revision 4d7946a68d (11 days ago), 2021-03-18 17:24:33 -0700
    • Engine revision 3459eb2436
    • Dart version 2.12.2

pubspec.yaml
  http: ^0.13.1

If it could catch the exception and proceed logically instead of crashing the app then maybe better.

bhtri avatar Mar 30 '21 07:03 bhtri

If it could catch the exception and proceed logically instead of crashing the app then maybe better.

so is there is a workaround?

EgHubs avatar Mar 30 '21 13:03 EgHubs

@EgHubs how did it workaround??

bhtri avatar Mar 31 '21 00:03 bhtri

@EgHubs how did it workaround??

Iam asking if you solved it.

EgHubs avatar Mar 31 '21 00:03 EgHubs

I still haven't solved it yet 😅

bhtri avatar Mar 31 '21 00:03 bhtri

+1

Vakil-Parth avatar Apr 12 '21 07:04 Vakil-Parth

I got a similar issue when using http.post and my test server is not running.

At least for my issue, it seems like IOClient is only catching HttpExceptions but somewhere in HttpClient.openUrl a SocketException can be thrown.

But I use some async code to catch the error and don't have issues with this; maybe worth trying for others with issues

return http
    .post(
  cloudUri,
  headers: { 'Content-Type': 'application/json'  },
  body: jsonString,
)
    .then((response) {
  if (response.statusCode == 200) {
    _log.fine('event sent');
    return Future.value();
  } else {
    _log.info('event could not be sent, status ${response.statusCode}');

    return Future.error(
        'http error code ${response.statusCode.toString()}');
  }
}).onError((error, stackTrace) {
  _log.warning('could not send event, error ', error);
  
  // catch error here
  return Future.value();
});

flo80 avatar Apr 12 '21 13:04 flo80

I also encountered this with a socket exception. Quite frustrating. SocketException: OS Error: Connection timed out, errno = 110, address = 192.168.0.1, port = 37694

edit:

I should clarify that I'm not just getting a random socket exception -- the method I'm calling that contains my http.get method is throwing a socket exception and then exiting the method without falling to any catch blocks.

Like flo80 said, this happens when the server in question is offline, meaning no response is possible.

0xNF avatar May 19 '21 01:05 0xNF

I have the same problem, but it seems to be a problem with flutter instead.

From the debugger it seems that exception is coming from the dart:io package

kdeoliveira avatar Jun 01 '21 23:06 kdeoliveira

Can someone provide a complete minimal reproduction case and instructions to see this behavior?

I have not been able to locally reproduce a case where using try, await, and catch doesn't catch the exception. When I run in an ios simulator the SocketException gets caught by exactly the catch block I'd expect.

natebosch avatar Jun 08 '21 22:06 natebosch

i have the same error with subdomains in localhost ( http://sub.localhost:80/example ) . But i have not in ( http://localhost:80 ), help me please.

Flutter try catch can't catch SocketException ( Exception has occurred. SocketException (SocketException: OS Error: No route to host, errno = 8)

david34corbalan avatar Aug 20 '21 13:08 david34corbalan

i have the same error

As above, we still need a reproduction case that we can debug.

natebosch avatar Aug 27 '21 00:08 natebosch

I solved the problem, when I use the package in localhost a vhost must be configured, that solved the problem. in my case use xampp with laravel in mac os.

example: in the terminal write "vim /etc/hosts" to edit vhost

Captura de Pantalla 2021-08-26 a la(s) 22 11 52

127.0.0.1 subdomain.localhost

david34corbalan avatar Aug 27 '21 01:08 david34corbalan

This issue is hard to spot, at least in my case, i only know it is happening when i see the crashlytics dashboard.

Crashlytics report

Non-fatal Exception: FlutterError
SocketException: Connection failed (OS Error: No route to host, errno = 65), address = dundermifflin.com, port = 443. Error thrown null.
Non-fatal Exception: FlutterError
0  ???                            0x0 _HttpClient.openUrl (dart:_http)
1  ???                            0x0 IOClient.send + 30 (io_client.dart:30)
2  ???                            0x0 BaseClient._sendUnstreamed + 93 (base_client.dart:93)
3  ???                            0x0 BaseClient.post + 32 (base_client.dart:32)
4  ???                            0x0 RestServiceBase.postData + 63 (rest_service_base.dart:63)
5  ???                            0x0 UserRestService.getNewNotifications + 206 (user_rest_service.dart:206)
6  ???                            0x0 LandingScreenStateProvider._pollNotifications + 298 (landing_state_provider.dart:298)

My code

@protected
  Future<Map<String, dynamic>> getData(Uri url) async {
    http.Response result;
    final httpClientInstance = new httpClient.IOClient();
    try {
      result = await httpClientInstance.get(url, headers: this._getHeaders());
    } catch (ex, s) {
      // process error
    } finally {
      httpClientInstance.close();
    }

    if (await _processResponseForTokenRefreshment(result)) {
      return getData(url);
    }

    return this._processResponse(result);
  }

joeloudjinz avatar Sep 24 '21 17:09 joeloudjinz

I came across the same issue today. It seems to be an error thrown inside the http package itself outside of the async/await context, so it cannot be handled by try-catch..

Looks like the issue is thrown in io_client.dart line 30:

var ioRequest = (await _inner!.openUrl(request.method, request.url))

Any progress on this?

Code to reproduce: https://github.com/dart-lang/http/pull/508#issuecomment-938508385

Marcel2508 avatar Oct 08 '21 09:10 Marcel2508

Any progress here?

alexaniko88 avatar Jan 25 '22 11:01 alexaniko88

Also having this issue. This bug is cluttering log outputs.

david-kooi avatar Jan 25 '22 18:01 david-kooi

I had the same issue, I'm not sure if my catch was only catching http errors but when I changed my try{} catch(e){}

to

try{ } on Exception catch (e) { }

it seems to work

ColbyClarke avatar Mar 03 '22 08:03 ColbyClarke

See this issue

We need to use the onError callback as well.

try {
   socket = socket.connect().onError((e){
    throw e as SocketException;
  })
} catch (e) {
   // Now it will finally get in the handler
}

Also, I programatically close the socket

await _socket?.close().onError((error, stackTrace) => null);

If I omit the onError, I get uncaught SocketExceptions. The weird thing is that I tried to add some logic in the onError (except returning null) and the app would crash. The annoying thing is that I can't properly debug, since it only happens on physical iOS devices when the app has been suspended by the OS.

Soo.... No clue what's going on here

laurensdewaele avatar May 12 '22 14:05 laurensdewaele

Calling the error throwing function inside runZonedGuarded helped me catch the error.

AliAkberAakash avatar Oct 25 '22 12:10 AliAkberAakash

Now good luck with WebSocketChannel.connect(), which isn't async and seems to wrap HTTPClient...

michpolicht avatar Jan 23 '23 06:01 michpolicht

In my case, removing the timeout duration specification seems to have fixed the error.

I changed somthing like this:

import 'package:http/http.dart' as http;

// ...

response = await http.post(
          Uri.http(theUri),
          headers: theHeaders,
          body: theBody,
        ).timeout(Duration(seconds: theTimeout));

into somenthing like this:

import 'package:http/http.dart' as http;

// ...

response = await http.post(
          Uri.http(theUri),
          headers: theHeaders,
          body: theBody,
        );

matcaste avatar Apr 05 '23 09:04 matcaste

I'm also experiencing this issue. And like @matcaste using a timeout on the http Future (get-Requests in my case) is the issue.

I'm sending multiple get requests, and it seems to me that with a timeout shorter than this packages internal timout you will run into this issue. Probably because the code execution has moved on already and the catch statement is no longer actively looking for something to catch.

EDIT: to clarify, this is indeed not a bug in http package, but a bug in Dart and Futures. Or my and others limited knowledge of Futures and not knowing how to correctly handle this behaviour. Here is a minimal reproducable example:

Future<void> main() async {
  try {
    var resultFuture = complexAsyncTask();
    var timeoutFuture = resultFuture.timeout(const Duration(seconds: 1), onTimeout: () {
      print("timeout");
      return "timeout return";
    });

    final String result = await timeoutFuture;

    print(result);
  } catch (e) {
    print("catched exception: $e");
  }
}

Future<String> complexAsyncTask() => _withTryFinallyAwait(() => _complexAsyncTask());

Future<T> _withTryFinallyAwait<T>(Future<T> Function() fn) async {
  try {
    return await fn();
  } finally {
    print("finally");
  }
}

Future<String> _complexAsyncTask() async {
  return await Future.delayed(const Duration(seconds: 2), () {
    throw Exception('exception thrown after 2 seconds delay');
    //return "success";
  });
}

If we await resultFuture (like in the example code), we have to wait for 2 seconds and the exception will be catched correctly. However, if we instead await the timeoutFuture (switch the comment to await resultFuture) we only wait for 1 second until the timeout happens and thrown Exception does NOT get catched.

Anybody knows how to wait only for the timeout but still catch an exception thrown in the async task ?

Sajonji avatar Jun 12 '23 14:06 Sajonji

Any update here?

Leobuaa avatar Aug 09 '23 01:08 Leobuaa

+1

MalouLandsgaard avatar Sep 01 '23 11:09 MalouLandsgaard

Hi, I got the same error and I fixed it by using

runZonedGuarded

here's my code

Future<Response?> post(String path, dynamic parameter) async =>
      runZonedGuarded<Future<Response?>>(() async {
        return await client.post(path,
            data: json.encode(parameter),
            options: Options(
              headers: headers
                ..addAll(<String, String>{
                  'Authorization': await localData.read(accessTokenName) ?? ''
                }),
            ));
      }, (error, stack) {
        throw Exception('SERVER DOWN');
      });

https://api.flutter.dev/flutter/dart-async/runZonedGuarded.html

for more explanation https://www.youtube.com/watch?v=pHpvfaanrbw&list=PLJbE2Yu2zumC4_aB75G2lQ-tAZlqIOGVx&index=3

bkan36 avatar Sep 26 '23 21:09 bkan36

BLESS YOU!!! @bkan36

CrownedComedian avatar Sep 29 '23 23:09 CrownedComedian

thanks @CrownedComedian. Do you have any mistakes when your server return a fail response like 400, 403... etc ?? After I've solved the socket exception uncaught I was trouble shooting another issue when my back-end return a failed response, So I tried to solve the problem, but unfortunately I wasn't successful, then I back to the version that worked and this code no longer works -___- (this weird issue has tired me);

At the moment I gave up and will continue to develop other features....

bkan36 avatar Sep 30 '23 18:09 bkan36

My situation is a bit different then that mentioned in this thread -- I was lucky to have even stumbled upon it. I've been working on an app to run provisioning code for my ESP device. Using Flutter's http package to communicate to the device abruptly ended my connection for some unknown reason, so I'm using platform specific code which seems to handle things. The exception I was getting was: java.net.SocketException: socket failed: ENONET (Machine is not on the network) And the basic gist of my Flutter/Dart code now includes:

Future<void> _runInZonedGuard() async {
  try {
    await _platform.invokeMethod(methodName, input).then((results) => {
      // cry happy tears
    }).onError((error, stack) => {
        // platform code called .error()
    });
  } catch (e) {
    // platform code threw exception
  }
}
runZonedGuarded(() => _runInZonedGuard(), (error, stack) {
  // I haven't gotten this to execute but it still works just fine
});

Then my platform code has the normal .setMethodCallHandler() with a switch statement in it that will run a call to my ESP device on a background thread via a Handler with a listener that will return .success() or .error() as usual. The SocketException was not being caught (even though other exceptions were) until I added your suggested code. Not sure if that answers your question, but maybe something you can try. Hope it helps! @bkan36

CrownedComedian avatar Oct 01 '23 00:10 CrownedComedian