Repository: sublimelsp/LSP

Issue:
LSP server initialization does not respond
This may be a bug upstream, but I haven't been able to reproduce it in VSCode, so I'm reporting here in case this appears to be an obvious problem with LSP-volar.

Reproduce steps:

1. Unzip [volar-starter-with-nodemodules.zip](https://github.com/sublimelsp/LSP-volar/files/11952697/volar-starter-with-nodemodules.zip) and open it in Sublime.
2. Open App.vue
3. Open LSP logs, you should see the initialization request sent, but no response received.

It's worth noting that if you delete node_modules and reinstall it via `pnpm i`, LSP will work fine.


Discussion:
We should handle that better on the LSP side by not just silently closing the server but this happens because we've received an unexpected payload from Volar's `stdout`. In this case it's

```
"Error: Cannot find module '@volar-plugins/prettyhtml'

Require stack:
- /Users/rafal/Downloads/volar-starter-with-nodemodules/volar.config.js
- /usr/local/workspace/github/volarjs/vue/node_modules/.pnpm/@volar+language-server@1.7.10/node_modules/@volar/language-server/out/common/utils/serverConfig.js
- /usr/local/workspace/github/volarjs/vue/node_modules/.pnpm/@volar+language-server@1.7.10/node_modules/@volar/language-server/out/common/server.js
- /usr/local/workspace/github/volarjs/vue/node_modules/.pnpm/@volar+language-server@1.7.10/node_modules/@volar/language-server/out/node/index.js
- /usr/local/workspace/github/volarjs/vue/node_modules/.pnpm/@volar+language-server@1.7.10/node_modules/@volar/language-server/node.js
- /usr/local/workspace/github/volarjs/vue/packages/vue-language-server/out/nodeServer.js
    at Module._resolveFilename (node:internal/modules/cjs/loader:963:15)
    at Module._load (node:internal/modules/cjs/loader:811:27)
    at f._load (node:electron/js2c/asar_bundle:2:13330)
    at Module.require (node:internal/modules/cjs/loader:1035:19)
    at require (node:internal/modules/cjs/helpers:102:18)
    at Object.<anonymous> (/Users/rafal/Downloads/volar-starter-with-nodemodules/volar.config.js:3:9)
    at Module._compile (node:internal/modules/cjs/loader:1141:14)
    at Module._extensions..js (node:internal/modules/cjs/loader:1196:10)
    at Module.load (node:internal/modules/cjs/loader:1011:32)
    at Module._load (node:internal/modules/cjs/loader:846:12) {
  code: 'MODULE_NOT_FOUND',
  requireStack: [
    '/Users/rafal/Downloads/volar-starter-with-nodemodules/volar.config.js',
    '/usr/local/workspace/github/volarjs/vue/node_modules/.pnpm/@volar+language-server@1.7.10/node_modules/@volar/language-server/out/common/utils/serverConfig.js',
    '/usr/local/workspace/github/volarjs/vue/node_modules/.pnpm/@volar+language-server@1.7.10/node_modules/@volar/language-server/out/common/server.js',
    '/usr/local/workspace/github/volarjs/vue/node_modules/.pnpm/@volar+language-server@1.7.10/node_modules/@volar/language-server/out/node/index.js',
    '/usr/local/workspace/github/volarjs/vue/node_modules/.pnpm/@volar+language-server@1.7.10/node_modules/@volar/language-server/node.js',
    '/usr/local/workspace/github/volarjs/vue/packages/vue-language-server/out/nodeServer.js'
  ]
}
Content-Length: 1906

"
```

I suppose that VSCode is either more permissive in handling `stdio` or it uses nodeipc instead (we can't switch to it yet due to reliance on Python 3.3).

I will still try to make some fix in LSP to surface those issues to the user.
And of course Volar should also post such errors to `stderr` and not `stdout` and either close itself or respond with error to `initialize`.
I see that you are actually using Node IPC for communicating with Volar in VSCode. Such issues don't affect IPC communication.
This is the problem line:  https://github.com/volarjs/volar.js/blob/master/packages/language-server/src/common/utils/serverConfig.ts#L17

I guess I should try to use `connection.logger` instead of `console`?
Yes. Or `console.error` but I suppose `console.error` would not be surfaced anywhere when using IPC so `connection.logger` seems more appropriate.
Thanks for confirming, I'll track it upstream.
I'll move this to LSP repo to handle this case better. It happened with eslint and other servers before.

Resolving patch:
diff --git a/plugin/core/transports.py b/plugin/core/transports.py
--- a/plugin/core/transports.py
+++ b/plugin/core/transports.py
@@ -66,13 +66,16 @@ def read_data(self, reader: IO[bytes]) -> Optional[Dict[str, Any]]:
         try:
             body = reader.read(int(headers.get("Content-Length")))
         except TypeError:
-            # Expected error on process stopping. Stop the read loop.
-            raise StopLoopError()
+            if str(headers) == '\n':
+                # Expected on process stopping. Gracefully stop the transport.
+                raise StopLoopError()
+            else:
+                # Propagate server's output to the UI.
+                raise Exception("Unexpected payload in server's stdout:\n\n{}".format(headers))
         try:
             return self._decode(body)
         except Exception as ex:
-            exception_log("JSON decode error", ex)
-            return None
+            raise Exception("JSON decode error: {}".format(ex))
 
     @staticmethod
     def _encode(data: Dict[str, Any]) -> bytes:
@@ -135,6 +138,7 @@ def __del__(self) -> None:
         self._join_thread(self._stderr_thread)
 
     def _read_loop(self) -> None:
+        exception = None
         try:
             while self._reader:
                 payload = self._processor.read_data(self._reader)
@@ -152,8 +156,11 @@ def invoke(p: T) -> None:
         except (AttributeError, BrokenPipeError, StopLoopError):
             pass
         except Exception as ex:
-            exception_log("Unexpected exception", ex)
-        self._send_queue.put_nowait(None)
+            exception = ex
+        if exception:
+            self._end(exception)
+        else:
+            self._send_queue.put_nowait(None)
 
     def _end(self, exception: Optional[Exception]) -> None:
         exit_code = 0


Test patch: