dart-redux-remote-devtools icon indicating copy to clipboard operation
dart-redux-remote-devtools copied to clipboard

'Future already completed' exception on iOS and macOS

Open nickmeinhold opened this issue 5 years ago • 8 comments
trafficstars

I've started getting this exception recently

  • occurs during app load
  • doesn't appear to stop remote-devtools working

[ERROR:flutter/lib/ui/ui_dart_state.cc(166)] Unhandled Exception: Bad state: Future already completed

Stack Trace
#0      _AsyncCompleter.complete  (dart:async/future_impl.dart:43:31)
#1      RemoteDevToolsMiddleware._waitForStart.<anonymous closure>> package:redux_remote_devtools/src/remote_devtools_middleware.dart:70
#2      Emitter.handleEmit package:socketcluster_client/src/emitter.dart:50
#3      Socket.handleMessage package:socketcluster_client/src/socket.dart:171
#4      _rootRunUnary  (dart:async/zone.dart:1198:47)
#5      _CustomZone.runUnary  (dart:async/zone.dart:1100:19)
#6      _CustomZone.runUnaryGuarded  (dart:async/zone.dart:1005:7)
#7      _BufferingStreamSubscription._sendData  (dart:async/stream_impl.dart:357:11)
#8      _BufferingStreamSubscription._add  (dart:async/stream_impl.dart:285:7)
#9      _SyncStreamControllerDispatch._sendData  (dart:async/stream_controller.dart:808:19)
#10     _StreamController._add  (dart:async/stream_controller.dart:682:7)
#11     _StreamController.add  (dart:async/stream_controller.dart:624:5)
#12     new _WebSocketImpl._fromSocket.<anonymous closure>  (dart:_http/websocket_impl.dart:1145:21)
#13     _rootRunUnary  (dart:async/zone.dart:1198:47)
#14     _CustomZone.runUnary  (dart:async/zone.dart:1100:19)
#15     _CustomZone.runUnaryGuarded  (dart:async/zone.dart:1005:7)
#16     _BufferingStreamSubscription._sendData  (dart:async/stream_impl.dart:357:11)
#17     _BufferingStreamSubscription._add  (dart:async/stream_impl.dart:285:7)
#18     _SinkTransformerStreamSubscription._add  (dart:async/stream_transformers.dart:69:11)
#19     _EventSinkWrapper.add  (dart:async/stream_transformers.dart:15:11)
#20     _WebSocketProtocolTransformer._messageFrameEnd  (dart:_http/websocket_impl.dart:338:23)
#21     _WebSocketProtocolTransformer.add  (dart:_http/websocket_impl.dart:232:46)
#22     _SinkTransformerStreamSubscription._handleData  (dart:async/stream_transformers.dart:121:24)
#23     _rootRunUnary  (dart:async/zone.dart:1198:47)
#24     _CustomZone.runUnary  (dart:async/zone.dart:1100:19)
#25     _CustomZone.runUnaryGuarded  (dart:async/zone.dart:1005:7)
#26     _BufferingStreamSubscription._sendData  (dart:async/stream_impl.dart:357:11)
#27     _BufferingStreamSubscription._add  (dart:async/stream_impl.dart:285:7)
#28     _SyncStreamControllerDispatch._sendData  (dart:async/stream_controller.dart:808:19)
#29     _StreamController._add  (dart:async/stream_controller.dart:682:7)
#30     _StreamController.add  (dart:async/stream_controller.dart:624:5)
#31     _Socket._onData  (dart:io-patch/socket_patch.dart:2020:41)
#32     _rootRunUnary  (dart:async/zone.dart:1206:13)
#33     _CustomZone.runUnary  (dart:async/zone.dart:1100:19)
#34     _CustomZone.runUnaryGuarded  (dart:async/zone.dart:1005:7)
#35     _BufferingStreamSubscription._sendData  (dart:async/stream_impl.dart:357:11)
#36     _BufferingStreamSubscription._add  (dart:async/stream_impl.dart:285:7)
#37     _SyncStreamControllerDispatch._sendData  (dart:async/stream_controller.dart:808:19)
#38     _StreamController._add  (dart:async/stream_controller.dart:682:7)
#39     _StreamController.add  (dart:async/stream_controller.dart:624:5)
#40     new _RawSocket.<anonymous closure>  (dart:io-patch/socket_patch.dart:1556:33)
#41     _NativeSocket.issueReadEvent.issue  (dart:io-patch/socket_patch.dart:1052:14)
#42     _microtaskLoop  (dart:async/schedule_microtask.dart:41:21)
#43     _startMicrotaskLoop  (dart:async/schedule_microtask.dart:50:5)

I made a minimal repro: https://github.com/nickmeinhold/test_rdt, it's just the starter project with the redux_remote_devtools package and

final remoteDevtools = RemoteDevToolsMiddleware('localhost:8000');
await remoteDevtools.connect();

added to main.dart

Thanks!

nickmeinhold avatar Jul 15 '20 12:07 nickmeinhold

Hey

I've just checked out your repo and it runs just fine for me (iOS simulator) after changing the IP address. What flutter channel are you on? It's possible a recent change has caused the issue.

Cheers Michael

MichaelMarner avatar Jul 15 '20 12:07 MichaelMarner

Also, what version of remotedev-server are you using? this exception may be caused by a change to the javascript package, not Flutter

MichaelMarner avatar Jul 15 '20 12:07 MichaelMarner

Hey Michael, thanks for this!

I'm on the dev channel for flutter, [email protected]

EDIT: I'm going to switch to stable and try

  • same issue for me when I switch to flutter stable
  • are you on an older version of remotedev-server? If so I should try going to that I guess, I'll check I get the issue on other computers too...

UPDATE:

  • I don't get the exception on my laptop, which is basically the same environment as my desktop (both are on the dev channel, using the same version of remotedev-server)
  • Sounds like this is a me problem, I'll report back if I figure out anything interesting

Thanks very much for your help!

nickmeinhold avatar Jul 15 '20 13:07 nickmeinhold

The only thing I can think of is the client is receiving the START message twice. I'm not sure why that would happen but perhaps it's worth checking to see whether we think we are already started and ignoring subsequent messages. Let me know if you are able to reliably reproduce and I'll see what I can do.

MichaelMarner avatar Jul 16 '20 01:07 MichaelMarner

Sweet thanks Michael! I followed your thought and added a check for status already being STARTED to _waitForStart, which stopped the exception and the package still works.

My plan at this point will be to use this edited version of redux_remote_devtools on my desktop and, given the problem seems to be something specific to this setup on my desktop, do a fresh install of the OS at some point (which I've been meaning to anyway). I'm happy to try and figure it out though if you want to try and get to the bottom of it.

Thanks again for your help.

nickmeinhold avatar Jul 16 '20 03:07 nickmeinhold

The Completer docs say:

Calling complete or completeError must be done at most once.

So even if receiving the START message twice is an error in remotedev-server, we shouldn't be calling complete twice.

If you've already done the change I'd be happy to accept a PR for this. Would just need a test to verify the behaviour.

MichaelMarner avatar Jul 17 '20 03:07 MichaelMarner

Thanks Michael, I had a go at writing a test but I haven't really worked with sockets before and I got a bit lost (even with plenty of your examples there). Also the exception has disappeared :-) I updated the OS, maybe that was it. I'd be happy to plough through if you think it's worth it but otherwise I'll leave it at that and be happy it's working for me again. Thanks for the great package!

nickmeinhold avatar Jul 17 '20 04:07 nickmeinhold

I'm having the same issue. The error doesn't appear consistently though.

  • I'm on MacOS.
  • Using redux-devtools-cli instead of remotedev-server, since as I mentioned in https://github.com/MichaelMarner/dart-redux-remote-devtools/issues/29#issuecomment-671065150 it didn't work for me.
  • Flutter stable channel.

Nimrodda avatar Aug 09 '20 15:08 Nimrodda