scalameta / metals-vscode

Visual Studio Code extension for Metals
https://marketplace.visualstudio.com/items?itemName=scalameta.metals#overview
Apache License 2.0
298 stars 75 forks source link

Getting `Failed to connect with build server....` while using devcontainer #1429

Closed ndlarsen closed 8 months ago

ndlarsen commented 11 months ago

Describe the bug

Using a devcontainer, on the first fresh import, or any subsequent container rebuild, metals-vscode fails with Failed to connect with build server, no functionality will work. See logs for more details., Reloading the project, using the previously built container, works as expected. All subsequent reloads without a container rebuild works as well. This behaviour seems pretty consistent.

To be fair, I am not fully convinced this is an issue with nor caused by metals-vscode as I am using a devcontainer and a custom definition at that. Who knows, this might even come down to local timing issues. Anyway, here's a bugreport. Please let me know if any additional information is required.

To Reproduce Steps to reproduce the behaviour:

  1. ensure all related containers not present
  2. import/(re)open a project
  3. observe devcontainer being built
  4. observer metals-vscode fail with Failed to connect with build server, no functionality will work. See logs for more details.
  5. reimport the project
  6. observe metals-vscode succeed

Expected behaviour

metals-vscode succeeding when connecting

Installation:

Additional context

Logs

output.metals.log terminal.log

Project files

devcontainer-scala.zip

Search terms

devcontainer docker

tgodzik commented 11 months ago

Thanks for reporting! Is it possible that some files are not kept in the devcontainer?

2023.10.05 07:32:02 WARN  Scala instance jar /home/vscode/.sbt/boot/scala-2.12.18/lib/scala-library.jar doesn't exist!

This should exist locally since the build was exported with those paths and it looks like they were removed (not cached)

It's possible to change the directories for keeping sbt and coursier caches, some examples here https://github.com/scalameta/metals-gitpod-sample/blob/master/gitpod_init.sh

ndlarsen commented 11 months ago

Hi @tgodzik

I appreciate your reply.

Thanks for reporting! Is it possible that some files are not kept in the devcontainer?

Generally, no, the entire project directory is mounted into the container under /workspace.

2023.10.05 07:32:02 WARN  Scala instance jar /home/vscode/.sbt/boot/scala-2.12.18/lib/scala-library.jar doesn't exist!

This should exist locally since the build was exported with those paths and it looks like they were removed (not cached)

These are only warnings related to non-cached files, though. If the presence of any file in the cache is a hard requirement, and breaks "normal" application flow, then I would argue that the log level is incorrect and that it is a weird design choice to begin with as caches are ephemeral by nature and cannot be relied upon. Really, if a given file is not present in the cache, the application should fetch and populate but I digress...

It's possible to change the directories for keeping sbt and coursier caches, some examples here https://github.com/scalameta/metals-gitpod-sample/blob/master/gitpod_init.sh

The downside of manually populating the cache is that one would need to update the container definition on each version change of both Scala and Metals, which I generally would like to avoid. Anyway, I tried it out (without cached container layers) just to see if this would change anything and as expected it did not. Rolling back the change and rebuilding (again without cached container layers) for some reason succeeded this time, even though the warnings you noted above related to the non-cached files was still present.

So, it is after all not super consistent and clearly there is a bug somewhere but as previously stated I am currently unable to pinpoint the cause. This just strengthens my belief that this is caused by either metals-vscode, ms-vscode-remote.remote-containers, scalameta.metals, any of the underlying dependencies or an interaction between any of the aforementioned. It does, though, sound a lot like a race condition somewhere and also a lot like some the bloop related issues I have seen reports of as well.

~Given my inability to pin-point the cause and the lack of consistent reproducibility, feel free to close the issue. After all, I can reopen it or open a new one if new information comes to light.~

Thanks again. Regards.

ndlarsen commented 11 months ago

Okay, so, quick update. Still unpredictable behaviour but I recently noticed the following:

I have attached the relevant part of metals.log + server.log and extension.remote.log.

In addition to this, I have noticed that an import of exactly the same configuration with exactly the same project files from time to time fails with different errors, java.util.concurrent.ExecutionException: org.eclipse.lsp4j.jsonrpc.MessageIssueException: Message could not be parsed. being one of them.

I hope this information brings you closer to pin-pointing a possible cause.

metals.log extension.host.remote.log server.log

tgodzik commented 10 months ago

Looks like the issue is indeed related to using json files generated in previous sessions.

When you run build import, the sbt Bloop plugin will populate .bloop/*.json files with paths that Bloop can use (it doesn't actually fetch most dependencies, though that could be changed.). When dev container is turned off, those caches are lost, but the json files contain those paths. That's why I suggested using the same trick we have in the example repo. You don't actually need to prepopulate the repos there, but the additional coursier cache setting make sure that artifacts are kept between sessions.

The reason for all this is that Bloop is just a build server, so it doesn't deal with resolution. The workaround here is to always import build when starting a dev container or use sbt via BSP, which will automatically download everything each time. You can use Metals: Switch build server command for that. I would however recommend tinkering with caches as that can reduce the startup time.