metals icon indicating copy to clipboard operation
metals copied to clipboard

underlying exception swallowed during codeAction

Open cvogt2 opened this issue 9 months ago • 5 comments

Describe the bug

We see metals stopping to provide completions and semantic highlighting in some cases and see this in the logs which looks like it swallows an underlying information, which would help to identify what causes the issue. As a first step we should reveal the CodeActionParams and the underlying information.

Mar 17, 2025 10:23:40 AM org.eclipse.lsp4j.jsonrpc.RemoteEndpoint fallbackResponseError
SEVERE: Internal error: An unexpected exception occurred while executing jsonrpc method public abstract java.util.concurrent.CompletableFuture scala.meta.metals.lsp.TextDocumentService.codeAction(org.eclipse.lsp4j.CodeActionParams)
java.lang.IllegalStateException: An unexpected exception occurred while executing jsonrpc method public abstract java.util.concurrent.CompletableFuture scala.meta.metals.lsp.TextDocumentService.codeAction(org.eclipse.lsp4j.CodeActionParams)
	at org.eclipse.lsp4j.jsonrpc.services.GenericEndpoint.lambda$recursiveFindRpcMethods$0(GenericEndpoint.java:73)
	at org.eclipse.lsp4j.jsonrpc.services.GenericEndpoint.request(GenericEndpoint.java:128)
	at org.eclipse.lsp4j.jsonrpc.RemoteEndpoint.handleRequest(RemoteEndpoint.java:271)
	at org.eclipse.lsp4j.jsonrpc.RemoteEndpoint.consume(RemoteEndpoint.java:201)
	at org.eclipse.lsp4j.jsonrpc.TracingMessageConsumer.consume(TracingMessageConsumer.java:119)
	at org.eclipse.lsp4j.jsonrpc.json.StreamMessageProducer.handleMessage(StreamMessageProducer.java:185)
	at org.eclipse.lsp4j.jsonrpc.json.StreamMessageProducer.listen(StreamMessageProducer.java:97)
	at org.eclipse.lsp4j.jsonrpc.json.ConcurrentMessageProcessor.run(ConcurrentMessageProcessor.java:114)
	at java.base/java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:539)
	at java.base/java.util.concurrent.FutureTask.run(FutureTask.java:264)
	at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1136)
	at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:635)
	at java.base/java.lang.Thread.run(Thread.java:840)

Expected behavior

No response

Operating system

None

Editor/Extension

VS Code

Version of Metals

v1.5.2

Extra context or search terms

No response

cvogt2 avatar Apr 09 '25 13:04 cvogt2

Thanks for reporting! Are there no other errors anywhere? Or anything in .metals/reports directory?

tgodzik avatar Apr 09 '25 16:04 tgodzik

I think we would have noticed if there were related errors in other places, but I'll look again next time I see this.

cvogt2 avatar Apr 10 '25 13:04 cvogt2

Worth mentioning we also hit this with another method (but this time it was textDocument/didChange):

java.lang.IllegalStateException: An unexpected exception occurred while executing jsonrpc method public abstract java.util.concurrent.CompletableFuture scala.meta.metals.lsp.TextDocumentService.didChange(org.eclipse.lsp4j.DidChangeTextDocumentParams)
    at org.eclipse.lsp4j.jsonrpc.services.GenericEndpoint.lambda$recursiveFindRpcMethods$0(GenericEndpoint.java:73)
    at org.eclipse.lsp4j.jsonrpc.services.GenericEndpoint.notify(GenericEndpoint.java:160)
    at org.eclipse.lsp4j.jsonrpc.RemoteEndpoint.handleNotification(RemoteEndpoint.java:231)
    at org.eclipse.lsp4j.jsonrpc.RemoteEndpoint.consume(RemoteEndpoint.java:198)
    at org.eclipse.lsp4j.jsonrpc.TracingMessageConsumer.consume(TracingMessageConsumer.java:119)
    at org.eclipse.lsp4j.jsonrpc.json.StreamMessageProducer.handleMessage(StreamMessageProducer.java:185)
    at org.eclipse.lsp4j.jsonrpc.json.StreamMessageProducer.listen(StreamMessageProducer.java:97)
    at org.eclipse.lsp4j.jsonrpc.json.ConcurrentMessageProcessor.run(ConcurrentMessageProcessor.java:114)
    at java.base/java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:539)
    at java.base/java.util.concurrent.FutureTask.run(FutureTask.java:264)
    at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1136)
    at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:635)
    at java.base/java.lang.Thread.run(Thread.java:840)

I'm pretty sure there again there was no underlying cause in that case as well.

Trying to walk through the code to reverse engineer how such an error log might be reached, I found:

  • lsp4j error comes from here
  • in order for the stacktrace to point up to this location, the error would've had to occur while constructing the CompletableFuture (not the execution of said future). That's totally something that might happen though, since Metals routinely has functions returning Future where some initial logic happens synchronously in the function call.
  • this is where it gets trickier... for there not to be some underlying cause printed after the exception, the InvocationTargetException would need to have its getCause be null
  • ChatGPT seemed to think that there might be issues if the underlying exception was from a class that isn't present in the classloader doing the invoke. That sounds potentially promising: it is totally possible for the error to be somewhere in Scala-version-specific presentation compiler instances and to reference some type that is only in that Scala compiler version (even more likely given this is another case where we're using 2.12.17 for the project, while the main Metals classloader would be loading Scala 2.13). That said, when I tried to verify this idea, I wasn't able to find anything and I'm starting to think it could just be a hallucination. 😄

harpocrates avatar Jun 22 '25 17:06 harpocrates

I think what Chat GPT said might be true when the classloaders are unrelated, in this case the main classloader is the parent of the 2.12.17 classloader. I also tried throwing exceptions both in the normal code and behind the classloader and both times I get the correct cause. I can't seem to figure out when it wouldn't have the cause.

It seems almost impossible based on lsp4j code 🤔

tgodzik avatar Jun 23 '25 15:06 tgodzik

Anyways, I also haven't seen this error since we fixed the thread safety issue around access to compiler issues, so priority isn't high. If/when it next occurs, I will be extra vigilant about double checking explicitly that there is no underlying cause (and collecting any other information)

harpocrates avatar Jun 23 '25 17:06 harpocrates