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

ElixirLS crashes due to "no function clause matching in ElixirLS.LanguageServer.Diagnostics.range/2" #707

Closed
kaikuchn opened this issue Jun 27, 2022 · 6 comments

Comments

@kaikuchn
Copy link

Environment

  • Elixir & Erlang versions (elixir --version):
Erlang/OTP 24 [erts-12.2] [source] [64-bit] [smp:4:4] [ds:4:4:10] [async-threads:1] [jit]

Elixir 1.13.1 (compiled with Erlang/OTP 23)
  • Elixir Language Server version: v0.10.0, ElixirLS compiled with Elixir 1.10.4 and erlang 22
  • Operating system: Ubuntu 20.04.3 LTS (Focal Fossa)
  • Editor or IDE name (e.g. Emacs/VSCode): VSCode
  • Editor Plugin/LSP Client name and version: ElixirLS: Elixir support and debugger v0.10.0

Current behavior

ElixirLS crashes after(/during?) the Analyzing modules step.

[Info  - 11:33:43 AM] [ElixirLS Dialyzer] Analyzing 3061 modules: [REDACTED, ...]
[Info  - 11:35:24 AM] [ElixirLS Dialyzer] Analysis finished in 188539 milliseconds

11:35:25.790 [error] GenServer ElixirLS.LanguageServer.Server terminating
** (FunctionClauseError) no function clause matching in ElixirLS.LanguageServer.Diagnostics.range/2
    (language_server 0.10.0) lib/language_server/diagnostics.ex:256: ElixirLS.LanguageServer.Diagnostics.range(-1, %ElixirLS.LanguageServer.SourceFile{dirty?: false, text: "defmodule MyApp.MyWorker do\n  use MyApp.BackgroundWorker, queue: :my_queue\n\n  require Logger\n\n  def execute(_) do\n    # REDACTED_CODE  end\nend\n", version: 1})
    (language_server 0.10.0) lib/language_server/diagnostics.ex:208: anonymous fn/3 in ElixirLS.LanguageServer.Diagnostics.publish_file_diagnostics/3
    (elixir 1.13.1) lib/enum.ex:2396: Enum."-reduce/3-lists^foldl/2-0-"/3
    (language_server 0.10.0) lib/language_server/diagnostics.ex:190: ElixirLS.LanguageServer.Diagnostics.publish_file_diagnostics/3
    (language_server 0.10.0) lib/language_server/server.ex:1064: anonymous fn/4 in ElixirLS.LanguageServer.Server.publish_diagnostics/3
    (elixir 1.13.1) lib/enum.ex:2396: Enum."-reduce/3-lists^foldl/2-0-"/3
    (language_server 0.10.0) lib/language_server/server.ex:1061: ElixirLS.LanguageServer.Server.publish_diagnostics/3
    (language_server 0.10.0) lib/language_server/server.ex:1001: ElixirLS.LanguageServer.Server.handle_dialyzer_result/3
Last message: {:"$gen_cast", {:dialyzer_finished, [...REDACTED..., %Mix.Task.Compiler.Diagnostic{compiler_name: "ElixirLS Dialyzer", details: {:warn_behaviour, {'lib/my_app/background_worker.ex', -1, {MyApp.MyWorker, :perform, 1}}, {:callback_type_mismatch, [Oban.Worker, :perform, 1, '[any()]', '\'discard\' | \'ok\' | {\'discard\',_} | {\'error\',_} | {\'ok\',_} | {\'snooze\',pos_integer()}']}}, file: "/workspaces/MyApp/lib/my_app/my_worker.ex", message: "background_worker.ex:-1: The inferred return type of perform/1 \n         ([any()]) has nothing in common with \n          'discard' | 'ok' |\n          {'discard', _} |\n          {'error', _} |\n          {'ok', _} |\n          {'snooze', pos_integer()}, which is the expected return type for the callback of the 'Elixir.Oban.Worker' behaviour", position: -1, severity: :warning} ...REDACTED... (truncated)
[Info  - 11:35:31 AM] Connection to server got closed. Server will restart.
[Error - 11:35:31 AM] Request textDocument/codeLens failed.
Error: Connection got disposed.
	at Object.dispose (/home/gitpod/.vscode-remote/extensions/jakebecker.elixir-ls-0.10.0/node_modules/vscode-jsonrpc/lib/common/connection.js:1044:27)
	at Object.dispose (/home/gitpod/.vscode-remote/extensions/jakebecker.elixir-ls-0.10.0/node_modules/vscode-languageclient/lib/common/client.js:73:35)
	at LanguageClient.handleConnectionClosed (/home/gitpod/.vscode-remote/extensions/jakebecker.elixir-ls-0.10.0/node_modules/vscode-languageclient/lib/common/client.js:2424:42)
	at LanguageClient.handleConnectionClosed (/home/gitpod/.vscode-remote/extensions/jakebecker.elixir-ls-0.10.0/node_modules/vscode-languageclient/lib/node/main.js:155:15)
	at closeHandler (/home/gitpod/.vscode-remote/extensions/jakebecker.elixir-ls-0.10.0/node_modules/vscode-languageclient/lib/common/client.js:2411:18)
	at CallbackList.invoke (/home/gitpod/.vscode-remote/extensions/jakebecker.elixir-ls-0.10.0/node_modules/vscode-jsonrpc/lib/common/events.js:55:39)
	at Emitter.fire (/home/gitpod/.vscode-remote/extensions/jakebecker.elixir-ls-0.10.0/node_modules/vscode-jsonrpc/lib/common/events.js:117:36)
	at closeHandler (/home/gitpod/.vscode-remote/extensions/jakebecker.elixir-ls-0.10.0/node_modules/vscode-jsonrpc/lib/common/connection.js:256:26)
	at CallbackList.invoke (/home/gitpod/.vscode-remote/extensions/jakebecker.elixir-ls-0.10.0/node_modules/vscode-jsonrpc/lib/common/events.js:55:39)
	at Emitter.fire (/home/gitpod/.vscode-remote/extensions/jakebecker.elixir-ls-0.10.0/node_modules/vscode-jsonrpc/lib/common/events.js:117:36)
	at StreamMessageReader.fireClose (/home/gitpod/.vscode-remote/extensions/jakebecker.elixir-ls-0.10.0/node_modules/vscode-jsonrpc/lib/common/messageReader.js:40:27)
	at Socket.<anonymous> (/home/gitpod/.vscode-remote/extensions/jakebecker.elixir-ls-0.10.0/node_modules/vscode-jsonrpc/lib/common/messageReader.js:125:42)
	at Socket.emit (node:events:402:35)
	at Pipe.<anonymous> (node:net:687:12)

Expected behavior

ElixirLS Dialyzer (? not sure who exactly) should not generate diagnostic output with a negative position and thus not crash the GenServer.
Here the spec says that the position should be always positive. However, the docs at the same time contradict this by saying that 0 represents unknown. That's also what's been implemented: the code for ElixirLS.LanguageServer.Diagnostics.range/2 deals with 0 as a special case, i.e., it can handle any non-negative integer positions.

@lukaszsamson
Copy link
Collaborator

Can you post a project that reproduces this error?

@kaikuchn
Copy link
Author

I tried to create a minimal project that reproduces the error. But I can't reproduce it. :/
Sadly I also cannot share the project where I'm encountering the issue.

How can I try to find out why/who created the diagnostics with a negative position? Is there some option to enable tracing?

@barttenbrinke
Copy link

barttenbrinke commented Jun 28, 2022

I have the same issue since yesterday on an unsharable project - it is an older style Elixir Umbrella app. Is there any info we can provide to help? BTW This project is awesome :D

@barttenbrinke
Copy link

barttenbrinke commented Jun 28, 2022

Could it be a version mismatch issue between ElixirLS and the project?

Elixir version: "1.10.3 (compiled with Erlang/OTP 21)"
Erlang version: "23"
ElixirLS compiled with Elixir 1.10.4 and erlang 22

cat .tool-versions
elixir 1.10.3
erlang 23.2.6

Erlang 22 vs 23 and 24 for the topic starter.

Btw, my diagnostic range is nil:

ElixirLS.LanguageServer.Diagnostics.range(nil, 

@lukaszsamson
Copy link
Collaborator

You can build elixirLS from source and inspect the diagnostics returned by dialyzer in

diagnostics = to_diagnostics(warnings, state.warn_opts, state.warning_format)
and elixir compiler in
case Kernel.ParallelCompiler.compile([mixfile]) do
and
case Mix.Task.run("compile", ["--return-errors", "--ignore-module-conflict"]) do

My suspicion is one of them is returning invalid data (both should never return negative values)

The other possible source of this error is

|> maybe_update_position(type, line, stacktrace)
- we do some normalization that may by broken

@barttenbrinke
Copy link

Thanks @lukaszsamson . Awesome work 👍

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

3 participants