Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

lsp starting stuck when open tramp file. #1845

Closed
tshu-w opened this issue Jun 26, 2020 · 21 comments
Closed

lsp starting stuck when open tramp file. #1845

tshu-w opened this issue Jun 26, 2020 · 21 comments

Comments

@tshu-w
Copy link

tshu-w commented Jun 26, 2020

Describe the bug
lsp starting stuck when open tramp file..

To Reproduce

  1. emacs -q -l lsp-start-plain.el
  2. C-x C-f /ssh:host_name:~/test/test.py to open an empty project with an empty python file.

my lsp-start-plain.el

(require 'package)

(setq debug-on-error t)

(let* ((package-archives '(("melpa" . "https://melpa.org/packages/")
                           ("gnu" . "https://elpa.gnu.org/packages/")))
       (no-byte-compile t)
       (package-user-dir (expand-file-name (make-temp-name "lsp-tmp-elpa")
                                           user-emacs-directory))
       (custom-file (expand-file-name "custom.el" package-user-dir))
       (pkg-list '(lsp-mode lsp-ui yasnippet lsp-java lsp-python-ms lsp-haskell helm-lsp lsp-treemacs dap-mode lsp-origami lsp-dart company flycheck)))

  (package-initialize)
  (package-refresh-contents)

  (mapcar (lambda (pkg)
            (unless (package-installed-p pkg)
              (package-install pkg))
            (require pkg))
          pkg-list)

  (add-hook 'prog-mode-hook 'lsp)
  (add-hook 'kill-emacs-hook `(lambda ()
                                (delete-directory ,package-user-dir t))))

(provide 'lsp-start-plain)
;;; lsp-start-plain.el ends here

(require 'tramp)
(add-to-list 'tramp-remote-path 'tramp-own-remote-path) ;; make execute-find pyls on remote

(with-eval-after-load 'lsp-mode
  (setq lsp-print-io t)

  (lsp-register-client
   (make-lsp-client :new-connection (lsp-tramp-connection "pyls")
                    :major-modes '(python-mode)
                    :remote? t
                    :server-id 'pyls-remote)))

Expected behavior
lsp start server correcting.

Which Language Server did you use
lsp-python

OS
Local: macOS GNU Emacs 27.0.91 (build 1, x86_64-apple-darwin19.5.0, NS appkit-1894.50 Version 10.15.5 (Build 19F101)) of 2020-06-20
remote: ubuntu

Error callstack
there is no error.
maybe related:

*lsp-log*:

Command "pyls" is present on the path.
Command "pyls" is present on the path.
Found the following clients for /ssh:is:/home/wts/test/test.py: (server-id pyls-remote, priority 0)
The following clients were selected based on priority: (server-id pyls-remote, priority 0)

*pyls-remote* is empty

*lsp-log: pyls-remote:28853*:

[Trace - 06:09:25 PM] Sending request 'initialize - (1)'.
Params: {
  "processId": null,
  "rootPath": "/home/wts/test",
  "clientInfo": {
    "name": "emacs",
    "version": "GNU Emacs 27.0.91 (build 1, x86_64-apple-darwin19.5.0, NS appkit-1894.50 Version 10.15.5 (Build 19F101))\n of 2020-06-20"
  },
  "rootUri": "file:///home/wts/test",
  "capabilities": {
    "workspace": {
      "workspaceEdit": {
        "documentChanges": true,
        "resourceOperations": [
          "create",
          "rename",
          "delete"
        ]
      },
      "applyEdit": true,
      "symbol": {
        "symbolKind": {
          "valueSet": [
            1,
            2,
            3,
            4,
            5,
            6,
            7,
            8,
            9,
            10,
            11,
            12,
            13,
            14,
            15,
            16,
            17,
            18,
            19,
            20,
            21,
            22,
            23,
            24,
            25,
            26
          ]
        }
      },
      "executeCommand": {
        "dynamicRegistration": false
      },
      "didChangeWatchedFiles": {
        "dynamicRegistration": true
      },
      "workspaceFolders": true,
      "configuration": true
    },
    "textDocument": {
      "declaration": {
        "linkSupport": true
      },
      "definition": {
        "linkSupport": true
      },
      "implementation": {
        "linkSupport": true
      },
      "typeDefinition": {
        "linkSupport": true
      },
      "synchronization": {
        "willSave": true,
        "didSave": true,
        "willSaveWaitUntil": true
      },
      "documentSymbol": {
        "symbolKind": {
          "valueSet": [
            1,
            2,
            3,
            4,
            5,
            6,
            7,
            8,
            9,
            10,
            11,
            12,
            13,
            14,
            15,
            16,
            17,
            18,
            19,
            20,
            21,
            22,
            23,
            24,
            25,
            26
          ]
        },
        "hierarchicalDocumentSymbolSupport": true
      },
      "formatting": {
        "dynamicRegistration": true
      },
      "rangeFormatting": {
        "dynamicRegistration": true
      },
      "rename": {
        "dynamicRegistration": true,
        "prepareSupport": true
      },
      "codeAction": {
        "dynamicRegistration": true,
        "isPreferredSupport": true,
        "codeActionLiteralSupport": {
          "codeActionKind": {
            "valueSet": [
              "",
              "quickfix",
              "refactor",
              "refactor.extract",
              "refactor.inline",
              "refactor.rewrite",
              "source",
              "source.organizeImports"
            ]
          }
        }
      },
      "completion": {
        "completionItem": {
          "snippetSupport": true,
          "documentationFormat": [
            "markdown"
          ]
        },
        "contextSupport": true
      },
      "signatureHelp": {
        "signatureInformation": {
          "parameterInformation": {
            "labelOffsetSupport": true
          }
        }
      },
      "documentLink": {
        "dynamicRegistration": true,
        "tooltipSupport": true
      },
      "hover": {
        "contentFormat": [
          "markdown",
          "plaintext"
        ]
      },
      "foldingRange": {
        "dynamicRegistration": true
      },
      "callHierarchy": {
        "dynamicRegistration": false
      },
      "publishDiagnostics": {
        "relatedInformation": true,
        "tagSupport": {
          "valueSet": [
            1,
            2
          ]
        },
        "versionSupport": true
      }
    },
    "window": {
      "workDoneProgress": true
    }
  },
  "initializationOptions": null,
  "workDoneToken": "1"
}
@tshu-w
Copy link
Author

tshu-w commented Jun 26, 2020

tmp/pyls-remote-1-stderr:

2020-06-26 18:09:27,104 UTC - ERROR - pyls_jsonrpc.streams - Failed to parse JSON message b'\n\n{"jsonrpc":"2.0","method":"initialize","params":{"processId":null,"rootPath":"/home/wts/test","clientInfo":{"name":"emacs","version":"GNU Emacs 27.0.91 (build 1, x86_64-apple-darwin19.5.0, NS appkit-1894.50 Version 10.15.5 (Build 19F101))\\n of 2020-06-20"},"rootUri":"file:///home/wts/test","capabilities":{"workspace":{"workspaceEdit":{"documentChanges":true,"resourceOperations":["create","rename","delete"]},"applyEdit":true,"symbol":{"symbolKind":{"valueSet":[1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26]}},"executeCommand":{"dynamicRegistration":false},"didChangeWatchedFiles":{"dynamicRegistration":true},"workspaceFolders":true,"configuration":true},"textDocument":{"declaration":{"linkSupport":true},"definition":{"linkSupport":true},"implementation":{"linkSupport":true},"typeDefinition":{"linkSupport":true},"synchronization":{"willSave":true,"didSave":true,"willSaveWaitUntil":true},"documentSymbol":{"symbolKind":{"valueSet":[1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26]},"hierarchicalDocumentSymbolSupport":true},"formatting":{"dynamicRegistration":true},"rangeFormatting":{"dynamicRegistration":true},"rename":{"dynamicRegistration":true,"prepareSupport":true},"codeAction":{"dynamicRegistration":true,"isPreferredSupport":true,"codeActionLiteralSupport":{"codeActionKind":{"valueSet":["","quickfix","refactor","refactor.extract","refactor.inline","refactor.rewrite","source","source.organizeImports"]}}},"completion":{"completionItem":{"snippetSupport":true,"documentationFormat":["markdown"]},"contextSupport":true},"signatureHelp":{"signatureInformation":{"parameterInformation":{"labelOffsetSupport":true}}},"documentLink":{"dynamicRegistration":true,"tooltipSupport":true},"hover":{"contentFormat":["markdown","plaintext"]},"foldingRange":{"dynamicRegistration":true},"callHierarchy":{"dynamicRegistration":false},"publishDiagnostics":{"relatedInformation":true,"tagSupport":{"valueSet":[1,2]},"versionSupport":true}},"window":{"workDoneProgress":true}},"initializationOptions":null,"workDoneToken":"1"},"id":1'
Traceback (most recent call last):
  File "/home/wts/.anaconda3/lib/python3.7/site-packages/pyls_jsonrpc/streams.py", line 40, in listen
    message_consumer(json.loads(request_str.decode('utf-8')))
ValueError: Unexpected character in found when decoding object value

@tshu-w
Copy link
Author

tshu-w commented Jun 28, 2020

after update 20200627.1217 this issue was fixed.

@tshu-w tshu-w closed this as completed Jun 28, 2020
@tshu-w tshu-w reopened this Jun 28, 2020
@yyoncho
Copy link
Member

yyoncho commented Jun 29, 2020

Seems like for some reason \r\n\r\n are converted to 4 \n when writing the message to the stream and pyls is failing to read that message.

@kiennq
Copy link
Member

kiennq commented Jun 29, 2020

Just saying but it might be because we're choosing utf-8 as byte en/decoder, we may should choose utf-8-unix instead, which will guarantee to not convert \r\n. Using just utf-8 will convert \r\n to either utf-8-dos, utf-8-unix, utf-8-mac depends on the system

@yyoncho
Copy link
Member

yyoncho commented Jun 29, 2020

maybe this is the problematic line:
(set-process-coding-system proc 'binary 'binary)

I mean it cant be us using utf-8 because the issue seems to happen when sending data.

@tshu-w can you try changing 'binary to 'utf-8-unix? Let me know if you need more help to try that.

@yyoncho
Copy link
Member

yyoncho commented Jun 29, 2020

Can you test (setq inhibit-eol-conversion t) as well

@tshu-w
Copy link
Author

tshu-w commented Jun 30, 2020

@yyoncho Neither of the above methods worked. I tried like this:

;; define fun !lsp-tramp-connection and change two `binaray' to `utf-8-unix'
(advice-add #'lsp-tramp-connection :override #'!lsp-tramp-connection)
;; or
(setq inhibit-eol-conversion t)

It's worth mentioning that occasionally I can successfully start the server.

@yyoncho
Copy link
Member

yyoncho commented Jun 30, 2020

These are variables to test as well:

coding-system-for-read
coding-system-for-write
last-coding-system-used

Without a reproducer, it is a guessing game. If none of these works I will ask the author of tramp to help with that.

@tshu-w
Copy link
Author

tshu-w commented Jun 30, 2020

None of the above variables works (;
I wish I could help further, but I don't know what to do.

@tshu-w
Copy link
Author

tshu-w commented Aug 17, 2020

@yyoncho I also try pyright, I got Server pyright-remote:56881 status:starting exited with status exit. Do you want to restart it? (y or n) n with no error reported.

@mjlbach
Copy link

mjlbach commented Aug 17, 2020

@tshu-w I use pyright over tramp. My settings are here: emacs-lsp/lsp-pyright#10

@tshu-w
Copy link
Author

tshu-w commented Aug 18, 2020

mjlbach's configuration works for me. I think the original problem was either in pyls or in the configuration in the documentation, I didn't delve into the make-lsp-client parameters

@abred
Copy link

abred commented Aug 26, 2020

tmp/pyls-remote-1-stderr:

2020-06-26 18:09:27,104 UTC - ERROR - pyls_jsonrpc.streams - Failed to parse JSON message b'\n\n{"jsonrpc":"2.0","method":"initialize","params":{"processId":null,"rootPath":"/home/wts/test","clientInfo":{"name":"emacs","version":"GNU Emacs 27.0.91 (build 1, x86_64-apple-darwin19.5.0, NS appkit-1894.50 Version 10.15.5 (Build 19F101))\\n of 2020-06-20"},"rootUri":"file:///home/wts/test","capabilities":{"workspace":{"workspaceEdit":{"documentChanges":true,"resourceOperations":["create","rename","delete"]},"applyEdit":true,"symbol":{"symbolKind":{"valueSet":[1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26]}},"executeCommand":{"dynamicRegistration":false},"didChangeWatchedFiles":{"dynamicRegistration":true},"workspaceFolders":true,"configuration":true},"textDocument":{"declaration":{"linkSupport":true},"definition":{"linkSupport":true},"implementation":{"linkSupport":true},"typeDefinition":{"linkSupport":true},"synchronization":{"willSave":true,"didSave":true,"willSaveWaitUntil":true},"documentSymbol":{"symbolKind":{"valueSet":[1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26]},"hierarchicalDocumentSymbolSupport":true},"formatting":{"dynamicRegistration":true},"rangeFormatting":{"dynamicRegistration":true},"rename":{"dynamicRegistration":true,"prepareSupport":true},"codeAction":{"dynamicRegistration":true,"isPreferredSupport":true,"codeActionLiteralSupport":{"codeActionKind":{"valueSet":["","quickfix","refactor","refactor.extract","refactor.inline","refactor.rewrite","source","source.organizeImports"]}}},"completion":{"completionItem":{"snippetSupport":true,"documentationFormat":["markdown"]},"contextSupport":true},"signatureHelp":{"signatureInformation":{"parameterInformation":{"labelOffsetSupport":true}}},"documentLink":{"dynamicRegistration":true,"tooltipSupport":true},"hover":{"contentFormat":["markdown","plaintext"]},"foldingRange":{"dynamicRegistration":true},"callHierarchy":{"dynamicRegistration":false},"publishDiagnostics":{"relatedInformation":true,"tagSupport":{"valueSet":[1,2]},"versionSupport":true}},"window":{"workDoneProgress":true}},"initializationOptions":null,"workDoneToken":"1"},"id":1'
Traceback (most recent call last):
  File "/home/wts/.anaconda3/lib/python3.7/site-packages/pyls_jsonrpc/streams.py", line 40, in listen
    message_consumer(json.loads(request_str.decode('utf-8')))
ValueError: Unexpected character in found when decoding object value

I get the same error. I'm not familiar with the code, or json, but could there somehow be a } missing at the end of the string? When I run json.loads(s.decode('utf-8)) with the string as is, I get a JSONDecodeError, but when I add a } at the end after "id":1} it works.

@nchodosh
Copy link

nchodosh commented Sep 25, 2020

@abred did you figure out what was causing this? I am having the same problem with a remote host and also am getting the error about the missing curly brace. I've checked and emacs is sending the correct string with matching braces but it's being truncated for some reason when sent.

EDIT:
I think i've found a dirty fix.
In lsp-mode.el in the function 'lsp--make-message' I changed (1+ (string-bytes body)) to (+ 2 (string-bytes body)) and that seems to fix it. My guess is that this is somehow miscalculating the size of the message and that's what is truncating the string

EDIT EDIT:
The new dirty fix is to just remove the carriage return characters from the message in lsp--make-message. Apparently they aren't needed for pyls to parse the message correctly. That actually appears to have fixed it and everything is working again.

@petr-tik
Copy link
Contributor

petr-tik commented Nov 4, 2020

EDIT:
I think i've found a dirty fix.
In lsp-mode.el in the function 'lsp--make-message' I changed (1+ (string-bytes body)) to (+ 2 (string-bytes body)) and that seems to fix it. My guess is that this is somehow miscalculating the size of the message and that's what is truncating the string

Using remote pyls over tramp and this dirty fix has worked for me. However, I have seen a similar error at work where I use lsp-clangd over tramp. It used to work fine, but after updating doom emacs (and lsp-mode with it) in the last week, i experience a similar error where the json of the message seems to be missing a curly brace at the end. For corporate policy reasons, I cannot share the clangd output, so it's good to see it reproducing with pyls. I will recover the commit differences and report tomorrow.

Before the dirty fix

@raspberrypi:~ $ pgrep pyls
6727
@raspberrypi:~ $ tail -f /proc/6727/fd/2
2020-11-04 22:27:39,803 UTC - ERROR - pyls_jsonrpc.streams - Failed to parse JSON message b'\n\n{"jsonrpc":"2.0","method":"initialize","params":{"processId":null,"rootPath":"/home/petr_tik","clientInfo":{"name":"emacs","version":"GNU Emacs 28.0.50 (build 1, x86_64-pc-linux-gnu, GTK+ Version 3.22.30, cairo version 1.15.10)\\n of 2020-10-22"},"rootUri":"file:///home/petr_tik","capabilities":{"workspace":{"workspaceEdit":{"documentChanges":true,"resourceOperations":["create","rename","delete"]},"applyEdit":true,"symbol":{"symbolKind":{"valueSet":[1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26]}},"executeCommand":{"dynamicRegistration":false},"didChangeWatchedFiles":{"dynamicRegistration":true},"workspaceFolders":true,"configuration":true},"textDocument":{"declaration":{"linkSupport":true},"definition":{"linkSupport":true},"implementation":{"linkSupport":true},"typeDefinition":{"linkSupport":true},"synchronization":{"willSave":true,"didSave":true,"willSaveWaitUntil":true},"documentSymbol":{"symbolKind":{"valueSet":[1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26]},"hierarchicalDocumentSymbolSupport":true},"formatting":{"dynamicRegistration":true},"rangeFormatting":{"dynamicRegistration":true},"rename":{"dynamicRegistration":true,"prepareSupport":true},"codeAction":{"dynamicRegistration":true,"isPreferredSupport":true,"codeActionLiteralSupport":{"codeActionKind":{"valueSet":["","quickfix","refactor","refactor.extract","refactor.inline","refactor.rewrite","source","source.organizeImports"]}}},"completion":{"completionItem":{"snippetSupport":true,"documentationFormat":["markdown"],"resolveAdditionalTextEditsSupport":true},"contextSupport":true},"signatureHelp":{"signatureInformation":{"parameterInformation":{"labelOffsetSupport":true}}},"documentLink":{"dynamicRegistration":true,"tooltipSupport":true},"hover":{"contentFormat":["markdown","plaintext"]},"foldingRange":{"dynamicRegistration":true},"callHierarchy":{"dynamicRegistration":false},"publishDiagnostics":{"relatedInformation":true,"tagSupport":{"valueSet":[1,2]},"versionSupport":true}},"window":{"workDoneProgress":true}},"initializationOptions":null,"workDoneToken":"1"},"id":1'
Traceback (most recent call last):
  File "/home/petr_tik/.local/lib/python3.7/site-packages/pyls_jsonrpc/streams.py", line 40, in listen
    message_consumer(json.loads(request_str.decode('utf-8')))
ValueError: Unexpected character in found when decoding object value

After applying the dirty fix and starting a new pyls

There is nothing in stderr.

@raspberrypi:~ $ pgrep pyls
7434
@raspberrypi:~ $ tail /proc/7434/fd/2

2 questions

Potentially unrelated

  1. For lsp servers that support it, why not start a http server and connect to it over tramp?
  2. Is it possible to get a buffer with pyls-stderr in emacs when running over tramp similar to when we run locally?

@tshu-w
Copy link
Author

tshu-w commented Jan 13, 2021

After a few days of testing, this issue has been solved in the latest tramp. For a detailed discussion see #2375 #2514

@Leonkoithara
Copy link

Hello sorry to comment on a closed issue however this was the closest issue matching mine, however I'm using tramp 2.5 installed from gnu

C-h v
Its value is "2.5.1.1"

Traceback (most recent call last):
File "${HOME}/.local/lib/python3.8/site-packages/pyls_jsonrpc/streams.py", line 40, in listen
message_consumer(json.loads(request_str.decode('utf-8')))
ValueError: Unexpected character in found when decoding object value

@tshu-w
Copy link
Author

tshu-w commented Aug 17, 2021

@Leonkoithara have you try #2531

(defun lsp-tramp-connection (local-command &optional generate-error-file-fn)
    "Create LSP stdio connection named name.
LOCAL-COMMAND is either list of strings, string or function which
returns the command to execute."
    (defvar tramp-connection-properties)
    ;; Force a direct asynchronous process.
    (when (file-remote-p default-directory)
      (add-to-list 'tramp-connection-properties
                   (list (regexp-quote (file-remote-p default-directory))
                         "direct-async-process" t)))
    (list :connect (lambda (filter sentinel name environment-fn)
                     (let* ((final-command (lsp-resolve-final-function
                                            local-command))
                            (_stderr (or (when generate-error-file-fn
                                           (funcall generate-error-file-fn name))
                                         (format "/tmp/%s-%s-stderr" name
                                                 (cl-incf lsp--stderr-index))))
                            (process-name (generate-new-buffer-name name))
                            (process-environment
                             (lsp--compute-process-environment environment-fn))
                            (proc (make-process
                                   :name process-name
                                   :buffer (format "*%s*" process-name)
                                   :command final-command
                                   :connection-type 'pipe
                                   :coding 'no-conversion
                                   :noquery t
                                   :filter filter
                                   :sentinel sentinel
                                   :file-handler t)))
                       (cons proc proc)))
          :test? (lambda () (-> local-command lsp-resolve-final-function
                           lsp-server-present?))))

@Leonkoithara
Copy link

I tried this but it didn't work although this time /tmp/pyls-*-stderr file was not created
Steps I took:

Replace lsp-tramp-connection function definition with snippet pasted above
M-x byte-recompile-directory ~/.emacs.d/elpa/lsp-mode-20210227.1401

find-function lsp-tramp-connection shows the updated code

@tshu-w
Copy link
Author

tshu-w commented Aug 21, 2021

Sorry, I don't have any ideas. Maybe you can create a new issue for it.

@jchax
Copy link

jchax commented Jan 28, 2024

Sorry to bring this up again, and hopefully this is in the right place. An earlier comment suggested changing lsp--make-message to change \r\n\r\n to just \n\n. I considered doing just that to make gopls work. In short, using gopls I see Content-Length: 3803\n\n\n\n{"jsonrpc"...} instead of Content-Length: 3803\r\n\r\n{"jsonrpc"...} but the solution isn't the hack, the solution is to terminate the body with \r\n instead of `\n':

(defun lsp--make-message (params)
  "Create a LSP message from PARAMS, after encoding it to a JSON string."
  (let ((body (lsp--json-serialize params)))
    (concat "Content-Length: "
            (number-to-string (1+ (string-bytes body)))
            "\r\n\r\n"
            body
            "\r\n")))

It's that last line that needed changing and that makes line endings a consistent CRLF and everything starts working.

(This is lsp-mode-20240116.1748 from ELPA, incidentally.)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

9 participants