vscode-firefox-debug icon indicating copy to clipboard operation
vscode-firefox-debug copied to clipboard

Flaky Remote Debugging under WSL2 with Parcel/React project, with ECONNREFUSED to 127.0.0.1

Open uglycoyote opened this issue 4 years ago • 4 comments

I am trying to make the switch to WSL (the newer version, WSL2) on Windows 10 since the build speeds are much faster, but being able to debug is the missing link.

I have created a barebones test project to try to run down why my breakpoints aren't working in WSL. I'm using Parcel for a bundler, VSCode with version 2.9.1 of vscode-firefox-debug

After an hour running it down I think it's likely that it is something about the way "localhost" works in WSL.

Debugging works fine for me when running this project on Windows10 outside WSL. When running under WSL2 I'm able to see logging output from Firefox but the breakpoints often don't work.

In the course of writing this issue, the WSL remote debugging mysteriously started working with no rhyme or reason, no change on my part, so I have included logs below from both a non-working and working run under WSL.

When running outside WSL, I can see even from the console.log's that the source maps are working correctly, because it prints "main.tsx:19" next to the console print statement

When running under WSL2, Firefox itself (inside the firefox console window) is printing Main.tsx next to the console statement, but in VSCode I see the bundle name instead (main.186cb047.js). So the fact that the breakpoints aren't working is indeed a source-map issue, but Firefox is able to use the sourcemaps fine, so it's more of an issue of VSCode getting the source maps.

In cases where it fails to work, the Diagostic output from vscode-firefox-debug prints far less lines. In cases where it's working properly, the output will contain the line

DEBUG|006.049|PathConversion: Converted url http://localhost:1234/main.tsx to path D:\mike\dev\simple-react-test\main.tsx

whereas in cases where it's not working, it never prints any line about main.tsx, but only about the bundles:

DEBUG|006.259|PathConversion: Converted url http://localhost:1234/main.186cb047.js.map to path vscode-remote://wsl%2Bubuntu/home/mike/simple-react-test/main.186cb047.js.map
ERROR|008.273|net: HTTP GET failed: Error: connect ECONNREFUSED 127.0.0.1:1234
DEBUG|008.274|PathConversion: Converted url http://localhost:1234/main.186cb047.js to path vscode-remote://wsl%2Bubuntu/home/mike/simple-react-test/main.186cb047.js
Download the React DevTools for a better development experience: https://reactjs.org/link/react-devtools

As mentioned, debugging mysteriously started working under WSL during these experiments at which point the WSL console output looked like the windows output.

So the question is, why under WSL does it sometimes not try to do the PathConversion for main.tsx?

Maybe the ECONNREFUSED in the logs above is the answer? I'm running parcel's server on localhost:1234. When running outside WSL, 127.0.0.1 is equivalent to localhost, but under WSL2, if parcel is serving on localhost:1234 and I try to browse to 127.0.0.1:1234 I get "unable to connect".

So perhaps the crux of this bug is that there's an assumption somewhere that 127.0.0.1 is equivalent to localhost, which is untrue in this environment. I don't know where that assumption is being made though.

My other thought is that maybe the last lines of these logs are a hint :

ERROR|007.998|EnvironmentAdapter: Unexpected function grip in function environment: {"displayName":"parcelRequire<[\"main.tsx\"]<"}
ERROR|007.999|EnvironmentAdapter: Unexpected function grip in function environment: {"displayName":"parcelRequire<[\"main.tsx\"]</TestComponent<"}
ERROR|007.999|EnvironmentAdapter: Unexpected function grip in function environment: {"displayName":"parcelRequire<[\"main.tsx\"]</TestComponent</TestComponent.prototype.increment"}

I don't know what this error is trying to tell me, but I searched the error and it does come from the codebase of vscode-firefox-debug:

https://github.com/firefox-devtools/vscode-firefox-debug/search?q=Unexpected+function+grip+in+function+environment

However I see these error messages even in cases where debugging is working fine, so that might be a red herring.

Below are the VSCode Console logs (with diagnostic output turned on) for the three situations:

  • Working properly under Windows
  • Not working, remote debugging under WSL2
  • working properly again (mysteriously) under WSL2

Windows VSCode Console Output (Debugging Working)

DEBUG|005.985|PathConversion: Converted url http://localhost:1234/main.186cb047.js.map to path D:\mike\dev\simple-react-test\main.186cb047.js.map
DEBUG|006.047|PathConversion: Converted url http://localhost:1234/node_modules/object-assign/index.js to path D:\mike\dev\simple-react-test\node_modules\object-assign\index.js
DEBUG|006.048|PathConversion: Converted url http://localhost:1234/node_modules/react/cjs/react.development.js to path D:\mike\dev\simple-react-test\node_modules\react\cjs\react.development.js
DEBUG|006.048|PathConversion: Converted url http://localhost:1234/node_modules/react/index.js to path D:\mike\dev\simple-react-test\node_modules\react\index.js
DEBUG|006.048|PathConversion: Converted url http://localhost:1234/node_modules/scheduler/cjs/scheduler.development.js to path D:\mike\dev\simple-react-test\node_modules\scheduler\cjs\scheduler.development.js
DEBUG|006.048|PathConversion: Converted url http://localhost:1234/node_modules/scheduler/index.js to path D:\mike\dev\simple-react-test\node_modules\scheduler\index.js
DEBUG|006.048|PathConversion: Converted url http://localhost:1234/node_modules/scheduler/cjs/scheduler-tracing.development.js to path D:\mike\dev\simple-react-test\node_modules\scheduler\cjs\scheduler-tracing.development.js
DEBUG|006.049|PathConversion: Converted url http://localhost:1234/node_modules/scheduler/tracing.js to path D:\mike\dev\simple-react-test\node_modules\scheduler\tracing.js
DEBUG|006.049|PathConversion: Converted url http://localhost:1234/node_modules/react-dom/cjs/react-dom.development.js to path D:\mike\dev\simple-react-test\node_modules\react-dom\cjs\react-dom.development.js
DEBUG|006.049|PathConversion: Converted url http://localhost:1234/node_modules/react-dom/index.js to path D:\mike\dev\simple-react-test\node_modules\react-dom\index.js
DEBUG|006.049|PathConversion: Converted url http://localhost:1234/main.tsx to path D:\mike\dev\simple-react-test\main.tsx
DEBUG|006.050|PathConversion: Converted url http://localhost:1234/node_modules/parcel/src/builtins/bundle-url.js to path D:\mike\dev\simple-react-test\node_modules\parcel\src\builtins\bundle-url.js
DEBUG|006.050|PathConversion: Converted url http://localhost:1234/node_modules/parcel/src/builtins/css-loader.js to path D:\mike\dev\simple-react-test\node_modules\parcel\src\builtins\css-loader.js
DEBUG|006.050|PathConversion: Converted url http://localhost:1234/node_modules/parcel/src/builtins/hmr-runtime.js to path D:\mike\dev\simple-react-test\node_modules\parcel\src\builtins\hmr-runtime.js
DEBUG|006.050|PathConversion: Converted url http://localhost:1234/main.186cb047.js to path D:\mike\dev\simple-react-test\main.186cb047.js
Download the React DevTools for a better development experience: https://reactjs.org/link/react-devtools
 react-dom.development.js
incrementing to 1
 main.tsx
ERROR|007.998|EnvironmentAdapter: Unexpected function grip in function environment: {"displayName":"parcelRequire<[\"main.tsx\"]<"}
ERROR|007.999|EnvironmentAdapter: Unexpected function grip in function environment: {"displayName":"parcelRequire<[\"main.tsx\"]</TestComponent<"}
ERROR|007.999|EnvironmentAdapter: Unexpected function grip in function environment: {"displayName":"parcelRequire<[\"main.tsx\"]</TestComponent</TestComponent.prototype.increment"}

WSL2 VSCode Console Output (Debugging Not Working)

DEBUG|006.259|PathConversion: Converted url http://localhost:1234/main.186cb047.js.map to path vscode-remote://wsl%2Bubuntu/home/mike/simple-react-test/main.186cb047.js.map
ERROR|008.273|net: HTTP GET failed: Error: connect ECONNREFUSED 127.0.0.1:1234
DEBUG|008.274|PathConversion: Converted url http://localhost:1234/main.186cb047.js to path vscode-remote://wsl%2Bubuntu/home/mike/simple-react-test/main.186cb047.js
Download the React DevTools for a better development experience: https://reactjs.org/link/react-devtools
 main.186cb047.js
incrementing to 1
 main.186cb047.js
incrementing to 2
 main.186cb047.js
incrementing to 3
 main.186cb047.js

WSL2 VSCode Console Output (Debugging Working)

Download the React DevTools for a better development experience: https://reactjs.org/link/react-devtools
DEBUG|006.217|PathConversion: Converted url http://localhost:1234/main.186cb047.js.map to path vscode-remote://wsl%2Bubuntu/home/mike/simple-react-test/main.186cb047.js.map
DEBUG|006.327|PathConversion: Converted url http://localhost:1234/node_modules/object-assign/index.js to path vscode-remote://wsl%2Bubuntu/home/mike/simple-react-test/node_modules/object-assign/index.js
DEBUG|006.329|PathConversion: Converted url http://localhost:1234/node_modules/react/cjs/react.development.js to path vscode-remote://wsl%2Bubuntu/home/mike/simple-react-test/node_modules/react/cjs/react.development.js
DEBUG|006.329|PathConversion: Converted url http://localhost:1234/node_modules/react/index.js to path vscode-remote://wsl%2Bubuntu/home/mike/simple-react-test/node_modules/react/index.js
DEBUG|006.329|PathConversion: Converted url http://localhost:1234/node_modules/scheduler/cjs/scheduler.development.js to path vscode-remote://wsl%2Bubuntu/home/mike/simple-react-test/node_modules/scheduler/cjs/scheduler.development.js
DEBUG|006.329|PathConversion: Converted url http://localhost:1234/node_modules/scheduler/index.js to path vscode-remote://wsl%2Bubuntu/home/mike/simple-react-test/node_modules/scheduler/index.js
DEBUG|006.329|PathConversion: Converted url http://localhost:1234/node_modules/scheduler/cjs/scheduler-tracing.development.js to path vscode-remote://wsl%2Bubuntu/home/mike/simple-react-test/node_modules/scheduler/cjs/scheduler-tracing.development.js
DEBUG|006.330|PathConversion: Converted url http://localhost:1234/node_modules/scheduler/tracing.js to path vscode-remote://wsl%2Bubuntu/home/mike/simple-react-test/node_modules/scheduler/tracing.js
DEBUG|006.330|PathConversion: Converted url http://localhost:1234/node_modules/react-dom/cjs/react-dom.development.js to path vscode-remote://wsl%2Bubuntu/home/mike/simple-react-test/node_modules/react-dom/cjs/react-dom.development.js
DEBUG|006.330|PathConversion: Converted url http://localhost:1234/node_modules/react-dom/index.js to path vscode-remote://wsl%2Bubuntu/home/mike/simple-react-test/node_modules/react-dom/index.js
DEBUG|006.330|PathConversion: Converted url http://localhost:1234/main.tsx to path vscode-remote://wsl%2Bubuntu/home/mike/simple-react-test/main.tsx
DEBUG|006.331|PathConversion: Converted url http://localhost:1234/node_modules/parcel/src/builtins/bundle-url.js to path vscode-remote://wsl%2Bubuntu/home/mike/simple-react-test/node_modules/parcel/src/builtins/bundle-url.js
DEBUG|006.331|PathConversion: Converted url http://localhost:1234/node_modules/parcel/src/builtins/css-loader.js to path vscode-remote://wsl%2Bubuntu/home/mike/simple-react-test/node_modules/parcel/src/builtins/css-loader.js
DEBUG|006.331|PathConversion: Converted url http://localhost:1234/node_modules/parcel/src/builtins/hmr-runtime.js to path vscode-remote://wsl%2Bubuntu/home/mike/simple-react-test/node_modules/parcel/src/builtins/hmr-runtime.js
DEBUG|006.331|PathConversion: Converted url http://localhost:1234/main.186cb047.js to path vscode-remote://wsl%2Bubuntu/home/mike/simple-react-test/main.186cb047.js
incrementing to 1
 main.tsx
incrementing to 2
 main.tsx
ERROR|009.315|EnvironmentAdapter: Unexpected function grip in function environment: {"displayName":"parcelRequire<[\"main.tsx\"]<"}
ERROR|009.316|EnvironmentAdapter: Unexpected function grip in function environment: {"displayName":"parcelRequire<[\"main.tsx\"]</TestComponent<"}
ERROR|009.317|EnvironmentAdapter: Unexpected function grip in function environment: {"displayName":"parcelRequire<[\"main.tsx\"]</TestComponent</TestComponent.prototype.increment"}

uglycoyote avatar Dec 11 '20 18:12 uglycoyote

Investigating this a bit further, it seems like a workaround is to avoid using localhost in the launch.json, but instead use the IP of the WSL instance directly:

from https://docs.microsoft.com/en-us/windows/wsl/compare-versions#accessing-network-applications

To find the IP address of the virtual machine powering your Linux distribution:

  • From your WSL distribution (ie Ubuntu), run the command: ip addr
  • Find and copy the address under the inet value of the eth0 interface.
  • If you have the grep tool installed, find this more easily by filtering the output with the command: ip addr | grep eth0
  • Connect to your Linux server using this IP address.

After finding the IP address under eth0, I used this in my VSCode launch profile

        {
            "name": "Firefox WSL",
            "type": "firefox",
            "request": "launch",
            "url": "http://192.168.17.69:1234/",

This seems to avoid the problem described above where it is using 127.0.0.1 falsely in place of localhost.

uglycoyote avatar Dec 11 '20 18:12 uglycoyote

@uglycoyote when I run yarn start from my wsl2, it'll give me the IP address same as what eth0 is if I use the ip addr command.

Basically it looks like this:

Compiled successfully!

You can now view personal-portfolio in the browser.

  Local:            http://localhost:3000
  On Your Network:  http://172.17.8.65:3000

Note that the development build is not optimized.
To create a production build, use yarn build.

webpack compiled successfully

The On Your Network part is where the IP matches. Putting that into my launch.json instead of localhost:3000 fixed my issue as a workaround, just as you suggested.

glitchwizard avatar Jan 20 '23 07:01 glitchwizard

@glitchwizard For a slightly cleaner approach than hard-coding the specific IP in to the launch.json, here's what I'm currently doing:

Line in my .zshrc startup script (.bashrc for most people?), which grabs the WSL IP address

export WSL2IP=$(ip addr show eth0 | grep -oP '(?<=inet\s)\d+(\.\d+){3}')

(courtesy of HRX's answer on https://superuser.com/questions/1586386/how-to-find-wsl2-machines-ip-address-from-windows)

Then in the launch.json, using the environment variable to fill in the IP address

        {
            "name": "Launch Chrome (WSL2)",
            "request": "launch",
            "type": "pwa-chrome",
            "url": "http://${env:WSL2IP}:1234",
        },

uglycoyote avatar Jan 20 '23 16:01 uglycoyote

@uglycoyote that's great, because I did notice that the IP changes from time to time. I'm not quite sure at this point what makes the IP change, but this is a great programmatic workaround.

glitchwizard avatar Jan 27 '23 15:01 glitchwizard