Skip to content

Eglot fails with Node type error

Hey there, probably not something to do with roc-ts-mode, but I'm at a loss. After starting the the language server I'm getting errors when I put the cursor on a function that the LSP has docs to display.

Syntax highlighting also barely works, the only thing that gets displayed in a different color are comments. (whether LSP is running or not)

Maybe you have an idea?

Versions

Emacs version: GNU Emacs 30.1 (build 2, x86_64-pc-linux-gnu, GTK+ Version 3.24.41, cairo version 1.18.0) of 2025-07-14 Roc version: roc nightly pre-release, built from commit c47a8e9 on Sa 22 Mar 2025 09:02:05 UTC (alpha3-*)

Roc file in buffer

app [main!] { cli: platform "https://github.com/roc-lang/basic-cli/releases/download/0.19.0/Hj-J_zxz7V9YurCSTFcFdu6cQJie4guzsPMUi5kBYUk.tar.br" }

import cli.Stdout
import cli.Arg exposing [Arg]

main! : List Arg => Result {} _
main! = |_args|
    List.range({ start: At(1), end: At(100) })
    |> List.map(fizz_buzz)
    |> Str.join_with(",")
    |> Stdout.line!

## Determine the FizzBuzz value for a given integer.
## Returns "Fizz" for multiples of 3, "Buzz" for
## multiples of 5, "FizzBuzz" for multiples of both
## 3 and 5, and the original number for anything else.
fizz_buzz : I32 -> Str
fizz_buzz = |n|
    fizz = n % 3 == 0
    buzz = n % 5 == 0

    if fizz and buzz then
        "FizzBuzz"
    else if fizz then
        "Fizz"
    else if buzz then
        "Buzz"
    else
        Num.to_str(n)

## Test Case 1: not a multiple of 3 or 5
expect fizz_buzz(1) == "1"
expect fizz_buzz(7) == "7"

## Test Case 2: multiple of 3
expect fizz_buzz(3) == "Fizz"
expect fizz_buzz(9) == "Fizz"

## Test Case 3: multiple of 5
expect fizz_buzz(5) == "Buzz"
expect fizz_buzz(20) == "Buzz"

## Test Case 4: multiple of both 3 and 5
expect fizz_buzz(15) == "FizzBuzz"
expect fizz_buzz(45) == "FizzBuzz"

Emacs config

(use-package roc-ts-mode
  :ensure t
  :mode ("\\.roc\\'" . roc-ts-mode)
  :config
  (add-to-list 'eglot-server-programs
               '(roc-ts-mode . ("roc_language_server"))))

Errors

(treesit-query-error "Node type error at" 515 "(where) @font-lock-keyword-face (implements) @font-lock-keyword-face (when) @font-lock-keyword-face (is) @font-lock-keyword-face (exposing) @font-lock-keyword-face \"if\" @font-lock-keyword-face \"then\" @font-lock-keyword-face \"else\" @font-lock-keyword-face \"as\" @font-lock-keyword-face \"dbg\" @font-lock-keyword-face \"expect\" @font-lock-keyword-face \"app\" @font-lock-keyword-face \"package\" @font-lock-keyword-face \"platform\" @font-lock-keyword-face \"module\" @font-lock-keyword-face \"exposes\" @font-lock-keyword-face \"imports\" @font-lock-keyword-face \"import\" @font-lock-keyword-face \"packages\" @font-lock-keyword-face \"requires\" @font-lock-keyword-face \"provides\" @font-lock-keyword-face" "Debug the query with `treesit-query-validate'")
  treesit--font-lock-fontify-region-1(#<treesit-node file in 1-203> #<treesit-compiled-query> 1 203 t nil)
  treesit-font-lock-fontify-region(1 203 nil)
  font-lock-fontify-syntactically-region(1 203 nil)
  font-lock-default-fontify-region(1 203 nil)
  indent-bars--fontify(1 203 nil)
  font-lock-fontify-region(1 203)
  #f(compiled-function (beg end) #<bytecode -0x6b246c2c8e17d0>)(1 203)
  font-lock-ensure()
  markdown-fontify-code-block-natively("roc" 149 350)
  markdown-fontify-code-blocks-generic(markdown-match-gfm-code-blocks 353)
  markdown-fontify-gfm-code-blocks(353)
  font-lock-fontify-keywords-region(1 353 nil)
  font-lock-default-fontify-region(1 353 nil)
  font-lock-fontify-region(1 353)
  #f(compiled-function (beg end) #<bytecode -0x6b246c2c8e17d0>)(1 353)
  font-lock-ensure()
  eglot--format-markup((:kind "markdown" :value "This works like [List.map], except only the transformed values that are\nwrapped in `Err` are kept. Any that are wrapped in `Ok` are dropped.\n```roc\nList.keep_errs([[\"a\", \"b\"], [], [], [\"c\", \"d\", \"e\"]], List.last)\n\nfn = \\str -> if Str.is_empty(str) then Err(StrWasEmpty) else Okd(Str.len(str))\n\nList.keep_errs([\"\", \"a\", \"bc\", \"\", \"d\", \"ef\", \"\"], fn)\n```"))
  #f(compiled-function (proxy) #<bytecode -0x1fa325615a92d41>)(#("keep_errs" 0 1 (eglot--lsp-item (:detail "List before, (before -> Result * after) -> List after" :documentation (:kind "markdown" :value "This works like [List.map], except only the transformed values that are\nwrapped in `Err` are kept. Any that are wrapped in `Ok` are dropped.\n```roc\nList.keep_errs([[\"a\", \"b\"], [], [], [\"c\", \"d\", \"e\"]], List.last)\n\nfn = \\str -> if Str.is_empty(str) then Err(StrWasEmpty) else Okd(Str.len(str))\n\nList.keep_errs([\"\", \"a\", \"bc\", \"\", \"d\", \"ef\", \"\"], fn)\n```") :kind 3 :label #1))))
  corfu-popupinfo--get-documentation(#("keep_errs" 0 1 (eglot--lsp-item (:detail "List before, (before -> Result * after) -> List after" :documentation (:kind "markdown" :value "This works like [List.map], except only the transformed values that are\nwrapped in `Err` are kept. Any that are wrapped in `Ok` are dropped.\n```roc\nList.keep_errs([[\"a\", \"b\"], [], [], [\"c\", \"d\", \"e\"]], List.last)\n\nfn = \\str -> if Str.is_empty(str) then Err(StrWasEmpty) else Okd(Str.len(str))\n\nList.keep_errs([\"\", \"a\", \"bc\", \"\", \"d\", \"ef\", \"\"], fn)\n```") :kind 3 :label #1))))
  corfu-popupinfo--show(#("keep_errs" 0 1 (eglot--lsp-item (:detail "List before, (before -> Result * after) -> List after" :documentation (:kind "markdown" :value "This works like [List.map], except only the transformed values that are\nwrapped in `Err` are kept. Any that are wrapped in `Ok` are dropped.\n```roc\nList.keep_errs([[\"a\", \"b\"], [], [], [\"c\", \"d\", \"e\"]], List.last)\n\nfn = \\str -> if Str.is_empty(str) then Err(StrWasEmpty) else Okd(Str.len(str))\n\nList.keep_errs([\"\", \"a\", \"bc\", \"\", \"d\", \"ef\", \"\"], fn)\n```") :kind 3 :label #1))))
  apply(corfu-popupinfo--show #("keep_errs" 0 1 (eglot--lsp-item (:detail "List before, (before -> Result * after) -> List after" :documentation (:kind "markdown" :value "This works like [List.map], except only the transformed values that are\nwrapped in `Err` are kept. Any that are wrapped in `Ok` are dropped.\n```roc\nList.keep_errs([[\"a\", \"b\"], [], [], [\"c\", \"d\", \"e\"]], List.last)\n\nfn = \\str -> if Str.is_empty(str) then Err(StrWasEmpty) else Okd(Str.len(str))\n\nList.keep_errs([\"\", \"a\", \"bc\", \"\", \"d\", \"ef\", \"\"], fn)\n```") :kind 3 :label #2))))
  timer-event-handler([t 26758 43688 652580 nil corfu-popupinfo--show (#("keep_errs" 0 1 (eglot--lsp-item (:detail "List before, (before -> Result * after) -> List after" :documentation (:kind "markdown" :value "This works like [List.map], except only the transformed values that are\nwrapped in `Err` are kept. Any that are wrapped in `Ok` are dropped.\n```roc\nList.keep_errs([[\"a\", \"b\"], [], [], [\"c\", \"d\", \"e\"]], List.last)\n\nfn = \\str -> if Str.is_empty(str) then Err(StrWasEmpty) else Okd(Str.len(str))\n\nList.keep_errs([\"\", \"a\", \"bc\", \"\", \"d\", \"ef\", \"\"], fn)\n```") :kind 3 :label #3)))) nil 599000 nil])
(treesit-query-error "Node type error at" 515 "(where) @font-lock-keyword-face (implements) @font-lock-keyword-face (when) @font-lock-keyword-face (is) @font-lock-keyword-face (exposing) @font-lock-keyword-face \"if\" @font-lock-keyword-face \"then\" @font-lock-keyword-face \"else\" @font-lock-keyword-face \"as\" @font-lock-keyword-face \"dbg\" @font-lock-keyword-face \"expect\" @font-lock-keyword-face \"app\" @font-lock-keyword-face \"package\" @font-lock-keyword-face \"platform\" @font-lock-keyword-face \"module\" @font-lock-keyword-face \"exposes\" @font-lock-keyword-face \"imports\" @font-lock-keyword-face \"import\" @font-lock-keyword-face \"packages\" @font-lock-keyword-face \"requires\" @font-lock-keyword-face \"provides\" @font-lock-keyword-face" "Debug the query with `treesit-query-validate'")
  treesit--font-lock-fontify-region-1(#<treesit-node ERROR in 1-37> #<treesit-compiled-query> 1 37 t nil)
  treesit-font-lock-fontify-region(1 37 nil)
  font-lock-fontify-syntactically-region(1 37 nil)
  font-lock-default-fontify-region(1 37 nil)
  indent-bars--fontify(1 37 nil)
  font-lock-fontify-region(1 37)
  #f(compiled-function (beg end) #<bytecode -0x6ff45b65ed17d0>)(1 37)
  font-lock-ensure()
  markdown-fontify-code-block-natively("roc" 8 43)
  markdown-fontify-code-blocks-generic(markdown-match-gfm-code-blocks 46)
  markdown-fontify-gfm-code-blocks(46)
  font-lock-fontify-keywords-region(1 46 nil)
  font-lock-default-fontify-region(1 46 nil)
  font-lock-fontify-region(1 46)
  #f(compiled-function (beg end) #<bytecode -0x6ff45b65ed17d0>)(1 46)
  font-lock-ensure()
  eglot--format-markup((:language "roc" :value "List I32, (I32 -> Str) -> List Str"))
  eglot--hover-info([(:language "roc" :value "List I32, (I32 -> Str) -> List Str")] (:end (:character 15 :line 8) :start (:character 7 :line 8)))
  #f(compiled-function (jsonrpc-lambda-elem14) #<bytecode 0x16b445e08147f97d>)((:contents [(:language "roc" :value "List I32, (I32 -> Str) -> List Str")] :range (:end (:character 15 :line 8) :start (:character 7 :line 8))))
  jsonrpc--continue(#<eglot-lsp-server eglot-lsp-server-1edc55551d85> 4 (4 :textDocument/hover #f(compiled-function (jsonrpc-lambda-elem14) #<bytecode 0x16b445e08147f97d>) #f(compiled-function (jsonrpc-lambda-elem3) #<bytecode 0x1a8c7fd64126af29>) [nil 26758 44047 310063 nil #f(compiled-function () #<bytecode 0xf8f330291afe683>) nil nil 345000 nil]) (:contents [(:language "roc" :value "List I32, (I32 -> Str) -> List Str")] :range (:end (:character 15 :line 8) :start (:character 7 :line 8))) nil)
  jsonrpc-connection-receive(#<eglot-lsp-server eglot-lsp-server-1edc55551d85> (:id 4 :jsonrpc "2.0" :result (:contents [(:language "roc" :value "List I32, (I32 -> Str) -> List Str")] :range (:end (:character 15 :line 8) :start (:character 7 :line 8)))))
  #f(compiled-function (conn msg) #<bytecode -0x3b168c7f7c89743>)(#<eglot-lsp-server eglot-lsp-server-1edc55551d85> (:id 4 :jsonrpc "2.0" :result (:contents [(:language "roc" :value "List I32, (I32 -> Str) -> List Str")] :range (:end (:character 15 :line 8) :start (:character 7 :line 8)))))
  apply(#f(compiled-function (conn msg) #<bytecode -0x3b168c7f7c89743>) (#<eglot-lsp-server eglot-lsp-server-1edc55551d85> (:id 4 :jsonrpc "2.0" :result (:contents [(:language "roc" :value "List I32, (I32 -> Str) -> List Str")] :range (:end (:character 15 :line 8) :start (:character 7 :line 8))))))
  timer-event-handler([t 26758 44037 335518 nil #f(compiled-function (conn msg) #<bytecode -0x3b168c7f7c89743>) (#<eglot-lsp-server eglot-lsp-server-1edc55551d85> (:id 4 :jsonrpc "2.0" :result (:contents [(:language "roc" :value "List I32, (I32 -> Str) -> List Str")] :range (:end (:character 15 :line 8) :start (:character 7 :line 8))))) nil 907000 nil])