navigator.lua icon indicating copy to clipboard operation
navigator.lua copied to clipboard

[bug] "Ruff failed to handle a request from the editor." Method: textDocument/codeAction error: missing field `range`

Open mpsijm opened this issue 10 months ago • 2 comments
trafficstars

When I press ]d to move to the next diagnostic message, about four–five seconds later I get the following error message:

image

This only started happening after installing the Navigator plugin, and I've received some help getting to the logs at https://github.com/astral-sh/ruff/issues/12523#issuecomment-2573247196. My lsp.log shows the following error:

JSON parsing failure:
Invalid request
Method: textDocument/codeAction
 error: missing field `range`

Oddly enough, the range field does appear to get passed to the textDocument/codeAction method:

Snippet of ~/.local/state/nvim/lsp.log, after I pressed `]d` at 08:18:50
[DEBUG][2025-01-09 08:18:54] ...m/lsp/client.lua:678    "LSP[pyright]"  "client.request"        3       "textDocument/codeAction"       {  context = {    diagnostics = { {        bufnr = 1,        code = "E741",        col = 0,        end_col = 1,        end_lnum = 2,        lnum = 2,        message = "Ambiguous variable name: `l`",        namespace = 21,        severity = 2,        source = "Ruff",        user_data = {          lsp = {            code = "E741",            codeDescription = {              href = "https://docs.astral.sh/ruff/rules/ambiguous-variable-name"            },            data = {              code = "E741",              edits = {},              kind = {                body = "Ambiguous variable name: `l`",                name = "AmbiguousVariableName"              },              noqa_edit = {                newText = "  # noqa: E741\n",                range = {                  ["end"] = {                    character = 0,                    line = 3                  },                  start = {                    character = 6,                    line = 2                  }                }              }            },            message = "Ambiguous variable name: `l`",            range = {              ["end"] = {                character = 1,                line = 2              },              start = {                character = 0,                line = 2              }            },            severity = 2,            source = "Ruff"          }        }      } },    only = { "quickfix", "source.organizeImports" }  },  range = {    ["end"] = <1>{      character = 0,      line = 2    },    start = <table 1>  },  textDocument = {    uri = "file:///home/maarten/git/contest/BAPCtools/tmp/test.py"  }}  <function 1>    1
[DEBUG][2025-01-09 08:18:54] .../vim/lsp/rpc.lua:286    "rpc.send"      {  id = 5,  jsonrpc = "2.0",  method = "textDocument/codeAction",  params = {    context = {      diagnostics = { {          bufnr = 1,          code = "E741",          col = 0,          end_col = 1,          end_lnum = 2,          lnum = 2,          message = "Ambiguous variable name: `l`",          namespace = 21,          severity = 2,          source = "Ruff",          user_data = {            lsp = {              code = "E741",              codeDescription = {                href = "https://docs.astral.sh/ruff/rules/ambiguous-variable-name"              },              data = {                code = "E741",                edits = {},                kind = {                  body = "Ambiguous variable name: `l`",                  name = "AmbiguousVariableName"                },                noqa_edit = {                  newText = "  # noqa: E741\n",                  range = {                    ["end"] = {                      character = 0,                      line = 3                    },                    start = {                      character = 6,                      line = 2                    }                  }                }              },              message = "Ambiguous variable name: `l`",              range = {                ["end"] = {                  character = 1,                  line = 2                },                start = {                  character = 0,                  line = 2                }              },              severity = 2,              source = "Ruff"            }          }        } },      only = { "quickfix", "source.organizeImports" }    },    range = {      ["end"] = <1>{        character = 0,        line = 2      },      start = <table 1>    },    textDocument = {      uri = "file:///home/maarten/git/contest/BAPCtools/tmp/test.py"    }  }}
[DEBUG][2025-01-09 08:18:54] ...m/lsp/client.lua:678    "LSP[ruff]"     "client.request"        4       "textDocument/codeAction"       {  context = {    diagnostics = { {        bufnr = 1,        code = "E741",        col = 0,        end_col = 1,        end_lnum = 2,        lnum = 2,        message = "Ambiguous variable name: `l`",        namespace = 21,        severity = 2,        source = "Ruff",        user_data = {          lsp = {            code = "E741",            codeDescription = {              href = "https://docs.astral.sh/ruff/rules/ambiguous-variable-name"            },            data = {              code = "E741",              edits = {},              kind = {                body = "Ambiguous variable name: `l`",                name = "AmbiguousVariableName"              },              noqa_edit = {                newText = "  # noqa: E741\n",                range = {                  ["end"] = {                    character = 0,                    line = 3                  },                  start = {                    character = 6,                    line = 2                  }                }              }            },            message = "Ambiguous variable name: `l`",            range = {              ["end"] = {                character = 1,                line = 2              },              start = {                character = 0,                line = 2              }            },            severity = 2,            source = "Ruff"          }        }      } },    only = { "quickfix", "source.organizeImports" }  },  range = {    ["end"] = <1>{      character = 0,      line = 2    },    start = <table 1>  },  textDocument = {    uri = "file:///home/maarten/git/contest/BAPCtools/tmp/test.py"  }}  <function 1>    1
[DEBUG][2025-01-09 08:18:54] .../vim/lsp/rpc.lua:286    "rpc.send"      {  id = 6,  jsonrpc = "2.0",  method = "textDocument/codeAction",  params = {    context = {      diagnostics = { {          bufnr = 1,          code = "E741",          col = 0,          end_col = 1,          end_lnum = 2,          lnum = 2,          message = "Ambiguous variable name: `l`",          namespace = 21,          severity = 2,          source = "Ruff",          user_data = {            lsp = {              code = "E741",              codeDescription = {                href = "https://docs.astral.sh/ruff/rules/ambiguous-variable-name"              },              data = {                code = "E741",                edits = {},                kind = {                  body = "Ambiguous variable name: `l`",                  name = "AmbiguousVariableName"                },                noqa_edit = {                  newText = "  # noqa: E741\n",                  range = {                    ["end"] = {                      character = 0,                      line = 3                    },                    start = {                      character = 6,                      line = 2                    }                  }                }              },              message = "Ambiguous variable name: `l`",              range = {                ["end"] = {                  character = 1,                  line = 2                },                start = {                  character = 0,                  line = 2                }              },              severity = 2,              source = "Ruff"            }          }        } },      only = { "quickfix", "source.organizeImports" }    },    range = {      ["end"] = <1>{        character = 0,        line = 2      },      start = <table 1>    },    textDocument = {      uri = "file:///home/maarten/git/contest/BAPCtools/tmp/test.py"    }  }}
[DEBUG][2025-01-09 08:18:54] .../vim/lsp/rpc.lua:408    "rpc.receive"   {  id = 5,  jsonrpc = "2.0",  result = {}}
[DEBUG][2025-01-09 08:18:54] .../vim/lsp/rpc.lua:408    "rpc.receive"   {  jsonrpc = "2.0",  method = "window/showMessage",  params = {    message = "Ruff failed to handle a request from the editor. Check the logs for more details.",    type = 1  }}
[DEBUG][2025-01-09 08:18:54] .../vim/lsp/rpc.lua:408    "rpc.receive"   {  error = {    code = -32603,    message = "JSON parsing failure:\nInvalid request\nMethod: textDocument/codeAction\n error: missing field `range`"  },  id = 6,  jsonrpc = "2.0"}
[TRACE][2025-01-09 08:18:54] ...m/lsp/client.lua:1003   "notification"  "window/showMessage"    {  message = "Ruff failed to handle a request from the editor. Check the logs for more details.",  type = 1}
[TRACE][2025-01-09 08:18:54] ...lsp/handlers.lua:711    "default_handler"       "window/showMessage"    {  ctx = '{\n  client_id = 4,\n  method = "window/showMessage"\n}',  result = {    message = "Ruff failed to handle a request from the editor. Check the logs for more details.",    type = 1  }}

What's also odd, is that the rpc.send arguments with ids 5 and 6 are identical, but the error is only shown for the request with id = 6, not for the one with id = 5.

By inserting some debug-prints at https://github.com/ray-x/navigator.lua/blob/master/lua/navigator/codeAction.lua#L153 and repeating the experiment after removing require('navigator').setup({ debug = 'trace' }) from my NeoVim Lua config, I've verified that these calls to the LSP that trigger the error are originating from Navigator.

I'm still quite new to NeoVim and Lua, can somebody help me with the next debugging step(s)?

mpsijm avatar Jan 09 '25 07:01 mpsijm

if I add a log

local code_action_req = function(_call_back_fn, context)
  local params = vim.lsp.util.make_range_params()
  log(params)
  params.context = context
  local line = params.range.start.line
  local callback = _call_back_fn(line, context.diagnostics)
  vim.lsp.buf_request(0, 'textDocument/codeAction', params, callback)
end

The log printout is

[INFO][Fri 10 Jan 16:57:45 2025] [3].../github/ray-x/navigator.lua/lua/navigator/codeAction.lua:152: {
  range = {
    ["end"] = <1>{
      character = 0,
      line = 0
    },
    start = <table 1>
  },
  textDocument = {
    uri = "file:///Users/rayxu/go/src/github.com/ray-x/history/history.py"
  }
}

So range is passed to ruff. Also in your logs, you can see that range is printed out

range = {              ["end"] = {                character = 1,                line = 2              },              start = {                character = 0,                line = 2              }            }

It must be something else.

ray-x avatar Jan 10 '25 06:01 ray-x

Yep, thanks for confirming my conclusion! Problem is, I have no idea where else to look, especially because everything appears to work as intended but still throws an error 😅

mpsijm avatar Jan 10 '25 06:01 mpsijm

So, I'm a bit late to the party but I managed to figure out what's causing Ruff to throw this error. For some reason, Ruff excepts a range parameter for each Diagnostic in params.context.diagnostics. I added the following snippet before passing params to the LSP request:

    for _, v in ipairs(params.context.diagnostics) do
        local range = nil
        if v.user_data.lsp.range ~= nil then
            range = v.user_data.lsp.range
        else
            range = v.user_data.lsp.data.range
        end
        v["range"] = range
    end

matbme avatar Jul 10 '25 13:07 matbme