Skip to main content

Proxy and mirrors

There are several parts inside Metals and Bloop that require resolving additional dependencies from the internet. Inside environments behind a proxy or with private artifact repositories Metals might not be able to start, because it cannot easily download the needed dependencies.

There are multiple ways of fixing these issues, but not all of them work in all situations. While we are trying to make it as painless as possible to setup everything, there are some steps that might need to be done manually.

Everything inside Metals uses Coursier to download its dependencies:

  • The Visual Studio Code and nvim-metals extensions both use Coursier to download Metals server, although they do it slightly different. The VS Code extension has a Coursier boostrap file, which is used to is to download a full Coursier version. It's used to keep the extension size down to a minimum, whereas nvim-metals requires Coursier to be installed on the users machine.
  • Metals uses Coursier api to download dependencies needed for a particular Scala version
  • Bloop uses Coursier api to download the SemanticDB plugin

You can find some more information about particular topics on Coursier's website, but we will try to summarize the most useful solutions here.

Mirrors

If Maven Central is not available for your workspace it might be best to use Coursier's mirrors. Especially since Coursier boostrap tries to download the core of Coursier from Maven Central directly, which can only be changed using the mirrors. Not all functionalities are yet available for the bootstrapped Coursier version, including custom repositories, so mirrors are really the only way to fix this.

There are different ways to setup mirrors:

Via global properties file

Create mirror.properties file with the contents:

central.from=https://repo1.maven.org/maven2
central.to=http://exmaple.com:8080/nexus/content/groups/public

You need to replace the uri after central.to= with your private repository.

The location of the mirror file varies depending on the operating system:

  • Windows: C:\Users\<user_name>\AppData\Roaming\Coursier\config\mirror.properties
  • Linux: ~/.config/coursier/mirror.properties
  • MacOS: ~/Library/Preferences/Coursier/mirror.properties

This solution will work in most cases for all previously mentioned usages of Coursier, which is especially important in the case of the Bloop server, which when started by Metals will not have any system properties forwarded.

Via environment variable

You can set the environment variable COURSIER_MIRRORS with the location of the file containing the mirror definition. That environment variable will need to available either locally or globally for the Metals server. In case of the Visual Studio Code extension it means you will need to start it from command line with that variable in scope.

Via properties

You can also use properties to specify the location of the mirror file, for example:

-Dcoursier.mirrors=~/.config/coursier/mirror.properties

This property needs to be added to the Metals server and Coursier invocation. However, this solution will not work for Bloop, because properties are not forwarded to the invocation of the Bloop server. You will need to use a different method for Bloop in this case or you can run the build server manually with everything specified separately.

Custom artifact repositories (Maven or Ivy resolvers)

In case you need to add custom repositories to resolve Metals server artifacts you can use the COURSIER_REPOSITORIES environment variable. This will tell Coursier to try to download artifacts from your private artifact repository. This is also available as a setting in the Metals Visual Studio Code and nvim-metals extensions.

Proxy settings

In some cases, workspaces might require a proxy in order to resolve the needed artifacts. Depending on the way Metals server is started, proxy settings can be specified using properties inside a .jvmopts file and metals.serverProperties for Visual Studio Code or serverProperties in your settings table for nvim-metals, or via properties for Coursier and Metals invocations.

However, because proxy properties might vary between workspaces and a Bloop server must work for multiple clients at the same time they are not forwarded to the Bloop itself. To make sure that Bloop uses the correct proxy settings, you can specify them by copying the correct .jvmopts file to the ~/.bloop directory, which will make them global.

If you are using a manually installed Bloop server, each time you run bloop from commandline, the proxy settings will be reapplied according to the current workspace's .jvmopts. This should not be an issue, since those settings are required only to download the compiler bridges and SemanticDB plugin.

Important Each setting needs to be on a separate line.

Troubleshooting

There has already been a couple of issues surrounding this topic, if you are still having issues you can take a look at some of them:

The server did not start, got FailedToOpenBspConnection

error: The command bsp --protocol tcp --port 44559 returned with an error
>
error: The launcher failed to establish a bsp connection, aborting...
ERROR Failed to connect with build server, no functionality will work.
java.lang.RuntimeException: The server did not start, got FailedToOpenBspConnection
at bloop.launcher.LauncherMain.failPromise$1(Launcher.scala:92)
at bloop.launcher.LauncherMain.runLauncher(Launcher.scala:119)
at scala.meta.internal.metals.BloopServers$$anon$1.run(BloopServers.scala:101)
at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:515)
at java.util.concurrent.FutureTask.run(FutureTask.java:264)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1128)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:628)
at java.lang.Thread.run(Thread.java:834)
Exception in thread "bloop-server-background" java.io.IOException: Cannot run program "java" (in directory "<some path here ...>"): error=2, No such file or directory
at java.lang.ProcessBuilder.start(ProcessBuilder.java:1048)

This might mean that you don't have your java installation on your PATH and Bloop was unable to start.

Timeout waiting for 'build/initialize' response

INFO  tracing is disabled for protocol BSP, to enable tracing of incoming and outgoing JSON messages create an empty file at C:\Users\tgodzik\AppData\Local\scalameta\metals\cache\bsp.trace.json
ERROR Timeout waiting for 'build/initialize' response
ERROR Failed to connect with build server, no functionality will work.
java.util.concurrent.TimeoutException
at java.util.concurrent.CompletableFuture.timedGet(CompletableFuture.java:1886)
at java.util.concurrent.CompletableFuture.get(CompletableFuture.java:2021)
at scala.meta.internal.metals.BuildServerConnection$.initialize(BuildServerConnection.scala:259)
at scala.meta.internal.metals.BuildServerConnection$.$anonfun$fromSockets$1(BuildServerConnection.scala:203)
at scala.util.Success.$anonfun$map$1(Try.scala:255)
at scala.util.Success.map(Try.scala:213)
at scala.concurrent.Future.$anonfun$map$1(Future.scala:292)
at scala.concurrent.impl.Promise.liftedTree1$1(Promise.scala:33)
at scala.concurrent.impl.Promise.$anonfun$transform$1(Promise.scala:33)
at scala.concurrent.impl.CallbackRunnable.run(Promise.scala:64)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1128)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:628)
at java.lang.Thread.run(Thread.java:834)

WARN Stopped configuration of SemanticDB in Scala 2.13.1 projects: Error downloading org.scalameta:semanticdb-scalac_2.13.1:4.3.0
not found: C:\Users\tgodzik\.ivy2\local\org.scalameta\semanticdb-scalac_2.13.1\4.3.0\ivys\ivy.xml
download error: Caught java.net.ConnectException: Connection timed out: connect (Connection timed out: connect) while downloading https://repo1.maven.org/maven2/org/scalameta/semanticdb-scalac_2.13.1/4.3.0/semanticdb-scalac_2.13.1-4.3.0.pom

This might mean you need to specify proxy settings for Bloop or add custom repositories as specified above.

Mirrors still do not work for all dependencies

In some specific configurations it might be needed to define additional mirrors like:

jcenter.from=https://repo1.maven.org/maven2
jcenter.to=https://artifactory.mycomany.com/maven2

typesafe.from=https://repo.typesafe.com/typesafe/ivy-releases
typesafe.to=https://artifactory.mycompany.com/typesafe-ivy-releases/

The number of repositories to add depends on how the company's infrastructure is set up. The key is to keep adding mirror entries until you've fixed each resolve error. In case of sbt you can find out what the repos are named like typesafe.from|to by checking the official documentation and any custom resolvers your workspace has defined.