Introduction

flutter で iOS 向けアプリのデバッグできない。
ios/Runnner.xcworkspace を xcode 開いてのデバッグは可能なのに、Visual Studio Code から F5 デバッグ時に

1
2
3
4
5
6
7
(lldb) 2023-09-16 15:45:17.269081+0900 Runner[26500:4300762] [VERBOSE-2:FlutterDarwinContextMetalImpeller.mm(37)] Using the Impeller rendering backend.
Connecting to the VM Service is taking longer than expected...
Still attempting to connect to the VM Service...
If you do NOT see the Flutter application running, it might have crashed. The device logs (e.g. from adb or XCode) might have more details.
If you do see the Flutter application running on the device, try re-running with --host-vmservice-port to use a specific port known to be available.
Exception attempting to connect to the VM Service: WebSocketException: Connection to 'http://127.0.0.1:5yyyyy/xxxxxxxxxxx/ws#' was not upgraded to websocket
This was attempt #50. Will retry in 0:00:01.600000.

のようなエラーが出てしまう。
エラーに含まれる、 yyyyyxxxxxxxxxxx は実行するたびに異なる。

How to resolve?

結論から言えば、proxy が原因。

メッセージを見ればわかるように、WebSocket による通信ができないと言っているが、これを阻害していたのが proxy。
ただ、proxy 設定では通常、 proxy を経由しない宛先のホストを指定できるので、そこに 127.0.0.1 を指定すれば回避できる。

が、ここで Windows 経験の長い人間は見事罠にはまった。
この特定のホストを proxy 経由から除外する設定は Windows とそれ以外の OS で指定方法に差がある。

Windows では ブラウザー設定を使用する にあるように

複数の例外はセミコロン (“;”) で区切る必要があります。

とある。

しかし、Mac では Macのプロキシ設定を変更する にあるように

バイパスするホストとドメインを入力します。複数の項目はカンマで区切ります。

とある。

つまり、複数指定する場合の区切り文字が異なっており、自分の場合、複数のホストを除外指定していたがためにこの問題に遭遇してしまっていた。
単純に 127.0.0.1 と指定したならば、何も起きなかったわけである。
環境変数も同様。

Windows

1
$ setx NO_PROXY "localhost;127.0.0.1"

Mac/Linux

1
$ export NO_PROXY="localhost,127.0.0.1"

区切り文字は環境に応じて適切な値を使用しましょう。
試していないが、 NO_PROXY は小文字、大文字どちらなのだろう。
Windows は区別しないが、Linux/OSX は明確に区別してるので。
参考: 開発メモ その211 boostを使った最小のCMakeプロジェクト その3

なお、この問題は flutter が原因ではなく、 dart の実装が原因。

Flutter (attach) expects NO_PROXY Environment Variable to be comma separated list on Windows.

This is an issue with Dart’s http implementation.

だそうです。

また、proxy に関係なく、デバッグ時に、このような 127.0.0.1 と通信できないというエラーは issue にあがっている。

上記はファイヤーウォールだったりする。
flutter tool がアプリと通信できないのが原因であるために、ファイヤーウォールが邪魔をすれば同じことが起きる (拒否されたとか)。

さらに言えば、このエラーは flutter test でも発生する。
上に書いたように、 flutter tool がアプリと通信できないというが原因なのだから当然である。