jedi-language-server icon indicating copy to clipboard operation
jedi-language-server copied to clipboard

Issues with Pickling (likely cause: semantic tokens)

Open pappasam opened this issue 1 year ago • 16 comments

Are you please able to take a look: https://github.com/microsoft/vscode-python/issues/25003#issuecomment-2828140646

We are almost there with vscode aupport; hitting a couple of issues though

Originally posted by @rivershah in #336

pappasam avatar Apr 25 '25 13:04 pappasam

@rivershah are you using notebook files, by any chance?

pappasam avatar Apr 25 '25 13:04 pappasam

No, this was a standard *.py file

rivershah avatar Apr 25 '25 14:04 rivershah

nvm, I can reproduce in neovim, so this will be easier for me to debug.

@seeM looks like this pickling error is starting with the notebook_utils file, any initial ideas on what the culprit could be?

  File "[REDACTED]/notebook_utils.py", line 373, in wrapped
    result = f(notebook_server, notebook_params)
             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

Error log from neovim:

[START][2025-04-25 10:54:13] LSP logging initiated
[ERROR][2025-04-25 10:54:13] ...p/_transport.lua:36	"rpc"	"jedi-language-server"	"stderr"	'WARNING:pygls.protocol.json_rpc:Cancel notification for unknown message id "15"\n'
[ERROR][2025-04-25 10:54:13] ...p/_transport.lua:36	"rpc"	"jedi-language-server"	"stderr"	"ERROR:pygls.protocol.json_rpc:Exception occurred for message \"15\": _pickle.UnpicklingError: invalid load key, ' '.\nNoneType: None\n"
[ERROR][2025-04-25 10:54:13] ...p/_transport.lua:36	"rpc"	"jedi-language-server"	"stderr"	"ERROR:pygls.protocol.json_rpc:Exception occurred for message \"16\": _pickle.UnpicklingError: invalid load key, ' '.\nNoneType: None\n"
[ERROR][2025-04-25 10:54:13] ...p/_transport.lua:36	"rpc"	"jedi-language-server"	"stderr"	"ERROR:pygls.protocol.json_rpc:Exception occurred for message \"17\": _pickle.UnpicklingError: invalid load key, ' '.\nNoneType: None\n"
[ERROR][2025-04-25 10:54:14] ...p/_transport.lua:36	"rpc"	"jedi-language-server"	"stderr"	"ERROR:pygls.protocol.json_rpc:Exception occurred for message \"18\": _pickle.UnpicklingError: invalid load key, ' '.\nNoneType: None\n"
[ERROR][2025-04-25 10:54:16] ...p/_transport.lua:36	"rpc"	"jedi-language-server"	"stderr"	"ERROR:pygls.protocol.json_rpc:Exception occurred for message \"19\": _pickle.UnpicklingError: invalid load key, ' '.\nNoneType: None\n"
[ERROR][2025-04-25 10:54:18] ...p/_transport.lua:36	"rpc"	"jedi-language-server"	"stderr"	"ERROR:pygls.protocol.json_rpc:Failed to handle request 20 textDocument/hover HoverParams(text_document=TextDocumentIdentifier(uri='file:///home/sroeca/src/pappasam/jedi-language-server/jedi_language_server/server.py'), position=719:58, work_done_token=None)\nTraceback (most recent call last):\n  File \"/home/sroeca/src/pappasam/jedi-language-server/.venv/lib/python3.12/site-packages/pygls/protocol/json_rpc.py\", line 266, in _handle_request\n    self._execute_request(msg_id, handler, params)\n  File \"/home/sroeca/src/pappasam/jedi-language-server/.venv/lib/python3.12/site-packages/pygls/protocol/json_rpc.py\", line 188, in _execute_request\n    self._send_response(msg_id, handler(params))\n                                ^^^^^^^^^^^^^^^\n  File \"/home/sroeca/src/pappasam/jedi-language-server/jedi_language_server/notebook_utils.py\", line 373, in wrapped\n    result = f(notebook_server, notebook_params)\n             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n  File \"/home/sroeca/src/pappasam/jedi-language-server/jedi_language_server/server.py\", line 487, in hover\n    jedi_script.help(*jedi_lines),\n    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n  File \"/home/sroeca/src/pappasam/jedi-language-server/.venv/lib/python3.12/site-packages/jedi/api/helpers.py\", line 487, in wrapper\n    return func(self, line, column, *args, **kwargs)\n           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n  File \"/home/sroeca/src/pappasam/jedi-language-server/.venv/lib/python3.12/site-packages/jedi/api/__init__.py\", line 372, in help\n    definitions = self.goto(line, column, follow_imports=True)\n                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n  File \"/home/sroeca/src/pappasam/jedi-language-server/.venv/lib/python3.12/site-packages/jedi/api/helpers.py\", line 487, in wrapper\n    return func(self, line, column, *args, **kwargs)\n           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n  File \"/home/sroeca/src/pappasam/jedi-language-server/.venv/lib/python3.12/site-packages/jedi/api/__init__.py\", line 300, in goto\n    names = list(name.goto())\n                 ^^^^^^^^^^^\n  File \"/home/sroeca/src/pappasam/jedi-language-server/.venv/lib/python3.12/site-packages/jedi/inference/names.py\", line 213, in goto\n    return context.goto(name, position=stmt.start_pos)\n           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n  File \"/home/sroeca/src/pappasam/jedi-language-server/.venv/lib/python3.12/site-packages/jedi/inference/context.py\", line 34, in goto\n    names = finder.filter_name(filters, name_or_str)\n            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n  File \"/home/sroeca/src/pappasam/jedi-language-server/.venv/lib/python3.12/site-packages/jedi/inference/finder.py\", line 35, in filter_name\n    for filter in filters:\n                  ^^^^^^^\n  File \"/home/sroeca/src/pappasam/jedi-language-server/.venv/lib/python3.12/site-packages/jedi/inference/context.py\", line 496, in get_global_filters\n    b = next(base_context.inference_state.builtins_module.get_filters(), None)\n             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n  File \"/home/sroeca/src/pappasam/jedi-language-server/.venv/lib/python3.12/site-packages/jedi/inference/cache.py\", line 44, in wrapper\n    rv = function(obj, *args, **kwargs)\n         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n  File \"/home/sroeca/src/pappasam/jedi-language-server/.venv/lib/python3.12/site-packages/jedi/inference/__init__.py\", line 129, in builtins_module\n    builtins_module, = self.import_module((module_name,), sys_path=[])\n                       ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n  File \"/home/sroeca/src/pappasam/jedi-language-server/.venv/lib/python3.12/site-packages/jedi/inference/__init__.py\", line 112, in import_module\n    return imports.import_module_by_names(\n           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n  File \"/home/sroeca/src/pappasam/jedi-language-server/.venv/lib/python3.12/site-packages/jedi/inference/imports.py\", line 377, in import_module_by_names\n    import_module(\n  File \"/home/sroeca/src/pappasam/jedi-language-server/.venv/lib/python3.12/site-packages/jedi/plugins/__init__.py\", line 21, in wrapper\n    return built_functions[public_name](*args, **kwargs)\n           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n  File \"/home/sroeca/src/pappasam/jedi-language-server/.venv/lib/python3.12/site-packages/jedi/plugins/flask.py\", line 20, in wrapper\n    return callback(inference_state, import_names, module_context, *args, **kwargs)\n           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n  File \"/home/sroeca/src/pappasam/jedi-language-server/.venv/lib/python3.12/site-packages/jedi/inference/gradual/typeshed.py\", line 115, in wrapper\n    python_value_set = ValueSet.from_sets(\n                       ^^^^^^^^^^^^^^^^^^^\n  File \"/home/sroeca/src/pappasam/jedi-language-server/.venv/lib/python3.12/site-packages/jedi/inference/base_value.py\", line 430, in from_sets\n    for set_ in sets:\n                ^^^^\n  File \"/home/sroeca/src/pappasam/jedi-language-server/.venv/lib/python3.12/site-packages/jedi/inference/gradual/typeshed.py\", line 116, in <genexpr>\n    func(inference_state, import_names, p, sys_path,)\n  File \"/home/sroeca/src/pappasam/jedi-language-server/.venv/lib/python3.12/site-packages/jedi/inference/imports.py\", line 411, in import_module\n    file_io_or_ns, is_pkg = inference_state.compiled_subprocess.get_module_info(\n                            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n  File \"/home/sroeca/src/pappasam/jedi-language-server/.venv/lib/python3.12/site-packages/jedi/inference/compiled/subprocess/__init__.py\", line 188, in wrapper\n    result = self._compiled_subprocess.run(\n             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n  File \"/home/sroeca/src/pappasam/jedi-language-server/.venv/lib/python3.12/site-packages/jedi/inference/compiled/subprocess/__init__.py\", line 296, in run\n    return self._send(inference_state_id, function, args, kwargs)\n           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n  File \"/home/sroeca/src/pappasam/jedi-language-server/.venv/lib/python3.12/site-packages/jedi/inference/compiled/subprocess/__init__.py\", line 318, in _send\n    is_exception, traceback, result = pickle_load(self._get_process().stdout)\n                                      ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n  File \"/home/sroeca/src/pappasam/jedi-language-server/.venv/lib/python3.12/site-packages/jedi/_compatibility.py\", line 25, in pickle_load\n    return Unpickler(file).load()\n           ^^^^^^^^^^^^^^^^^^^^^^\n_pickle.UnpicklingError: invalid load key, ' '.\n"
[ERROR][2025-04-25 10:54:18] .../vim/lsp/buf.lua:66	-32603	"_pickle.UnpicklingError: invalid load key, ' '."
[ERROR][2025-04-25 10:56:41] ...p/_transport.lua:36	"rpc"	"jedi-language-server"	"stderr"	"ERROR:pygls.protocol.json_rpc:Exception occurred for message \"21\": _pickle.UnpicklingError: invalid load key, ' '.\nNoneType: None\n"

Formatted traceback:

ERROR:pygls.protocol.json_rpc:Failed to handle request 20 textDocument/hover HoverParams(text_document=TextDocumentIdentifier(uri='file:///home/sroeca/src/pappasam/jedi-language-server/jedi_language_server/server.py'), position=719:58, work_done_token=None)
Traceback (most recent call last):
  File "/home/sroeca/src/pappasam/jedi-language-server/.venv/lib/python3.12/site-packages/pygls/protocol/json_rpc.py", line 266, in _handle_request
    self._execute_request(msg_id, handler, params)
  File "/home/sroeca/src/pappasam/jedi-language-server/.venv/lib/python3.12/site-packages/pygls/protocol/json_rpc.py", line 188, in _execute_request
    self._send_response(msg_id, handler(params))
                                ^^^^^^^^^^^^^^^
  File "/home/sroeca/src/pappasam/jedi-language-server/jedi_language_server/notebook_utils.py", line 373, in wrapped
    result = f(notebook_server, notebook_params)
             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/sroeca/src/pappasam/jedi-language-server/jedi_language_server/server.py", line 487, in hover
    jedi_script.help(*jedi_lines),
    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/sroeca/src/pappasam/jedi-language-server/.venv/lib/python3.12/site-packages/jedi/api/helpers.py", line 487, in wrapper
    return func(self, line, column, *args, **kwargs)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/sroeca/src/pappasam/jedi-language-server/.venv/lib/python3.12/site-packages/jedi/api/__init__.py", line 372, in help
    definitions = self.goto(line, column, follow_imports=True)
                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/sroeca/src/pappasam/jedi-language-server/.venv/lib/python3.12/site-packages/jedi/api/helpers.py", line 487, in wrapper
    return func(self, line, column, *args, **kwargs)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/sroeca/src/pappasam/jedi-language-server/.venv/lib/python3.12/site-packages/jedi/api/__init__.py", line 300, in goto
    names = list(name.goto())
                 ^^^^^^^^^^^
  File "/home/sroeca/src/pappasam/jedi-language-server/.venv/lib/python3.12/site-packages/jedi/inference/names.py", line 213, in goto
    return context.goto(name, position=stmt.start_pos)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/sroeca/src/pappasam/jedi-language-server/.venv/lib/python3.12/site-packages/jedi/inference/context.py", line 34, in goto
    names = finder.filter_name(filters, name_or_str)
            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/sroeca/src/pappasam/jedi-language-server/.venv/lib/python3.12/site-packages/jedi/inference/finder.py", line 35, in filter_name
    for filter in filters:
                  ^^^^^^^
  File "/home/sroeca/src/pappasam/jedi-language-server/.venv/lib/python3.12/site-packages/jedi/inference/context.py", line 496, in get_global_filters
    b = next(base_context.inference_state.builtins_module.get_filters(), None)
             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/sroeca/src/pappasam/jedi-language-server/.venv/lib/python3.12/site-packages/jedi/inference/cache.py", line 44, in wrapper
    rv = function(obj, *args, **kwargs)
         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/sroeca/src/pappasam/jedi-language-server/.venv/lib/python3.12/site-packages/jedi/inference/__init__.py", line 129, in builtins_module
    builtins_module, = self.import_module((module_name,), sys_path=[])
                       ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/sroeca/src/pappasam/jedi-language-server/.venv/lib/python3.12/site-packages/jedi/inference/__init__.py", line 112, in import_module
    return imports.import_module_by_names(
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/sroeca/src/pappasam/jedi-language-server/.venv/lib/python3.12/site-packages/jedi/inference/imports.py", line 377, in import_module_by_names
    import_module(
  File "/home/sroeca/src/pappasam/jedi-language-server/.venv/lib/python3.12/site-packages/jedi/plugins/__init__.py", line 21, in wrapper
    return built_functions[public_name](*args, **kwargs)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/sroeca/src/pappasam/jedi-language-server/.venv/lib/python3.12/site-packages/jedi/plugins/flask.py", line 20, in wrapper
    return callback(inference_state, import_names, module_context, *args, **kwargs)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/sroeca/src/pappasam/jedi-language-server/.venv/lib/python3.12/site-packages/jedi/inference/gradual/typeshed.py", line 115, in wrapper
    python_value_set = ValueSet.from_sets(
                       ^^^^^^^^^^^^^^^^^^^
  File "/home/sroeca/src/pappasam/jedi-language-server/.venv/lib/python3.12/site-packages/jedi/inference/base_value.py", line 430, in from_sets
    for set_ in sets:
                ^^^^
  File "/home/sroeca/src/pappasam/jedi-language-server/.venv/lib/python3.12/site-packages/jedi/inference/gradual/typeshed.py", line 116, in <genexpr>
    func(inference_state, import_names, p, sys_path,)
  File "/home/sroeca/src/pappasam/jedi-language-server/.venv/lib/python3.12/site-packages/jedi/inference/imports.py", line 411, in import_module
    file_io_or_ns, is_pkg = inference_state.compiled_subprocess.get_module_info(
                            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/sroeca/src/pappasam/jedi-language-server/.venv/lib/python3.12/site-packages/jedi/inference/compiled/subprocess/__init__.py", line 188, in wrapper
    result = self._compiled_subprocess.run(
             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/sroeca/src/pappasam/jedi-language-server/.venv/lib/python3.12/site-packages/jedi/inference/compiled/subprocess/__init__.py", line 296, in run
    return self._send(inference_state_id, function, args, kwargs)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/sroeca/src/pappasam/jedi-language-server/.venv/lib/python3.12/site-packages/jedi/inference/compiled/subprocess/__init__.py", line 318, in _send
    is_exception, traceback, result = pickle_load(self._get_process().stdout)
                                      ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/sroeca/src/pappasam/jedi-language-server/.venv/lib/python3.12/site-packages/jedi/_compatibility.py", line 25, in pickle_load
    return Unpickler(file).load()
           ^^^^^^^^^^^^^^^^^^^^^^
_pickle.UnpicklingError: invalid load key, ' '.

pappasam avatar Apr 25 '25 15:04 pappasam

What is workaround? Rollback to the previous release?

daskol avatar Apr 25 '25 22:04 daskol

workaround is to just use the release prior to the landing of notebook support. If we can't figure this out soon, I'm just going to disable notebook support and make a new release.

pappasam avatar Apr 25 '25 22:04 pappasam

I’m on vacation atm so unfortunately can’t guarantee I’ll be able to look at this soon.

What were the steps to repro this?

Does removing the notebook decorators fix it? They’re only first in the trace because of the decorator approach, but I’m not sure from the logs if that is the root cause.

seeM avatar Apr 26 '25 08:04 seeM

@seeM the culprit appears to be semantic tokens, so feel free to ignore. Have a great vacation!

@daskol @rivershah disabling semantic tokens appears to prevent this issue from happening in practice, so I've disabled them by default in the latest release: https://github.com/pappasam/jedi-language-server/releases/tag/v0.45.1

pappasam avatar Apr 27 '25 13:04 pappasam

@TechPizzaDev looks like semanticTokens wasn't quite ready for primetime after all. No rush (thanks to the toggle, semantic tokens were easy to disable by default), but figure this issue will be of interest to you if you've got some ideas about root causes / possible mitigation strategies.

pappasam avatar Apr 27 '25 13:04 pappasam

I had constant pickling issues before I started writing the PR. I can look into it but I feel this was a problem already. Maybe the thread decorator makes the issue worse by desyncing the request ID?

TechPizzaDev avatar Apr 27 '25 13:04 TechPizzaDev

Hmm, appreciate your observation! I'll look into that in a bit and see if I can determine a root cause. I always appreciate help if you have the time, but your comment has already been helpful

pappasam avatar Apr 27 '25 15:04 pappasam

By simply removing SERVER.thread(), things appear to work fine (correctly, but slow on large files). @TechPizzaDev Any objections to removing this decorator?

pappasam avatar Apr 27 '25 15:04 pappasam

I only added/copied that decorator since PR https://github.com/pappasam/jedi-language-server/pull/231 also had it. I had pickling issues with Intellisense hovers before I wrote this PR, but no other methods use Server.thread() so I'm not sure. I'd comment the decorator out with a note saying it's unstable for now.

Further work should probably go into Jedi itself, exposing a faster/specialized jedi_script.get_names method that only returns a specific range to make _semantic_tokens_range significantly faster.

TechPizzaDev avatar Apr 28 '25 09:04 TechPizzaDev

Thanks for looking at this. Just so I am fully up to speed, now that the vscode devs have exposed the relevant settings for jedi-language-server for semantic highlight, we don't need to request any further refactors from them?

As we refactor here, it just flows through to vscode ms-python extension?

rivershah avatar Apr 28 '25 10:04 rivershah

The activation settings seem to be hardcoded in vscode-python and as mentioned by https://github.com/microsoft/vscode-python/issues/25003#issuecomment-2828140646, jedi-language-server does not have config exposed i.e. semantic highlight is always enabled. Outside of that, changes should indeed flow with vscode-python releases AFAIK.

TechPizzaDev avatar Apr 28 '25 10:04 TechPizzaDev

Hope this feature can be implemented soon. I am really looking forward to have semantic highlighting in my python script

ntluong95 avatar May 14 '25 12:05 ntluong95

The symptoms in my case was that the LSP features would work for a few seconds upon opening a project, then go into an infinite loading state upon clicking an xref after those few seconds. The debug console would indeed show the error mentioned in this thread. Restarting the Python LSP would make it work again for a few seconds, repeatably.

By simply removing SERVER.thread(), things appear to work fine (correctly, but slow on large files). @TechPizzaDev Any objections to removing this decorator?

Gosh, thanks for this. This has been driving me insane for months. Simply killing the two instances of SERVER.thread() in ~/.vscode/extensions/ms-python.python-2025.10.0-linux-x64/python_files/lib/jedilsp/jedi_language_server/server.py made Python LSP work again.

zopieux avatar Jul 15 '25 17:07 zopieux