bug#81514: 32.0.50; Eglot messages progress reporter shows errors
João Távora <[email protected]> Thu, 30 Jul 2026 00:25:45 +0100
| Newsgroups | gmane.emacs.bugs |
|---|---|
| Message-ID | <CALDnm53xuFbmkweFnV+HyE58kiSrGbLX9jmeBBrpVLP0_j0PsQ@mail.gmail.com> |
Haven't read it, but see lots of + and only one - which makes me frown. What was so wrong in Eglot's use of this facility, which worked fine afaict until your changes? João João Távora On Wed, Jul 29, 2026, 21:28 Stéphane Marks <[email protected]> wrote: > On Wed, Jul 29, 2026 at 3:59 PM João Távora <[email protected]> wrote: > >> Hi! >> >> If there are confirmed failings in Eglot's usage of progress reporters, >> fixes are welcome. >> >> That said, please tread carefully: said fixes must not endanger (or >> worsen in any way) the backward compatibility of eglot.el all the way to at >> least Emacs 27, where these progress reporters didn't exist or were more >> primitive. I'd also appreciate if said fixes are succinct in nature, and >> not architecture-changing... >> >> Thanks! >> João >> >> >> >> >> >> >> >> >> >> On Wed, Jul 29, 2026, 20:33 Stéphane Marks <[email protected]> wrote: >> >>> On Wed, Jul 29, 2026 at 2:47 PM Stéphane Marks <[email protected]> >>> wrote: >>> >>>> On Wed, Jul 29, 2026 at 11:17 AM Jacek Świerk <[email protected]> >>>> wrote: >>>> >>>>> I can reproduce it with clangd on the following C++ repository: >>>>> https://github.com/rui314/mold. It doesn't happen every time but >>>>> often enough: >>>>> >>>>> Debugger entered--Lisp error: (wrong-type-argument sequencep 100) >>>>> ((20 . [1785337541.907988 nil nil "[eglot] mold >>>>> backgroundIndexProgress: indexing..." 1 0.2 nil nil]) 20 100) >>>>> progress-reporter-do-update((20 . [1785337541.907988 nil nil >>>>> "[eglot] mold backgroundIndexProgress: indexing..." 1 0.2 nil nil]) 100 nil) >>>>> eglot--reporter-update((20 . [1785337541.907988 nil nil "[eglot] >>>>> mold backgroundIndexProgress: indexing..." 1 0.2 nil nil]) 100 nil) >>>>> #f(compiled-function (arg1 arg2 arg3 arg4 &rest rest) #<bytecode >>>>> 0xa1216d65848076a>)(#<eglot-lsp-server 1022b7360904> >>>>> "backgroundIndexProgress" 100 nil) >>>>> #f(compiled-function (arg1 arg2 &rest rest) "Handle $/progress >>>>> notification identified by TOKEN from SERVER." #<bytecode >>>>> -0xf68beacb9f43862>)(#<eglot-lsp-server 1022b7360904> $/progress :token >>>>> "backgroundIndexProgress" :value (:kind "end")) >>>>> apply(#f(compiled-function (arg1 arg2 &rest rest) "Handle $/progress >>>>> notification identified by TOKEN from SERVER." #<bytecode >>>>> -0xf68beacb9f43862>) #<eglot-lsp-server 1022b7360904> $/progress (:token >>>>> "backgroundIndexProgress" :value (:kind "end"))) >>>>> eglot-handle-notification(#<eglot-lsp-server 1022b7360904> >>>>> $/progress :token "backgroundIndexProgress" :value (:kind "end")) >>>>> apply(eglot-handle-notification #<eglot-lsp-server 1022b7360904> >>>>> $/progress (:token "backgroundIndexProgress" :value (:kind "end"))) >>>>> #f(compiled-function (server method params) #<bytecode >>>>> 0x1f1b657efb0838aa>)(#<eglot-lsp-server 1022b7360904> $/progress (:token >>>>> "backgroundIndexProgress" :value (:kind "end"))) >>>>> jsonrpc-connection-receive(#<eglot-lsp-server 1022b7360904> >>>>> (:jsonrpc "2.0" :method "$/progress" :params (:token >>>>> "backgroundIndexProgress" :value (:kind "end")))) >>>>> #f(compiled-function (conn msg) #<bytecode >>>>> 0x4e6153735258fd3>)(#<eglot-lsp-server 1022b7360904> (:jsonrpc "2.0" >>>>> :method "$/progress" :params (:token "backgroundIndexProgress" :value >>>>> (:kind "end")))) >>>>> apply(#f(compiled-function (conn msg) #<bytecode 0x4e6153735258fd3>) >>>>> (#<eglot-lsp-server 1022b7360904> (:jsonrpc "2.0" :method "$/progress" >>>>> :params (:token "backgroundIndexProgress" :value (:kind "end"))))) >>>>> timer-event-handler([t 27242 5829 902968 nil #f(compiled-function >>>>> (conn msg) #<bytecode 0x4e6153735258fd3>) (#<eglot-lsp-server 1022b7360904> >>>>> (:jsonrpc "2.0" :method "$/progress" :params (:token >>>>> "backgroundIndexProgress" :value (:kind "end")))) nil 894000 nil]) >>>>> >>>>> The LSP message that causes it looks like this from the >>>>> (eglot-events-buffer): >>>>> <-- $/progress >>>>> {"jsonrpc":"2.0","method":"$/progress","params":{"token":"backgroundIndexProgress","value":{"kind":"end"}}} >>>>> >>>>> Based on my understanding of Eglot code, Eglot creates a non-numeric >>>>> progress >>>>> reporter because MIN-VALUE and MAX-VALUE arguments are not provided. >>>>> However, it >>>>> looks like Eglot updates the created progress reporter as it were >>>>> numeric: >>>>> (eglot--reporter-update pr pcnt msg) >>>>> >>>>> For the {"kind": "end"} notification, pcnt is set to 100 and msg is >>>>> nil. After >>>>> commit b6849229003, the pulsing reporter forwards (or update-text >>>>> value) as >>>>> UPDATE-TEXT. That evaluates to 100. Then progress-reporter-echo-area >>>>> tries >>>>> (concat (if update-text " " "") update-text) which triggers the shown >>>>> error. >>>>> >>>> I was able to reproduce the issue without eglot and will take a look. >>>> >>>> Coincidentally, and independent of the issue, eglot seems to want a >>>> numeric reporter but instead creates a non-numeric reporter. eglot-handle-notification >>>> method seems to also be missing the call to progress-reporter-done >>>> that would clear any stateful reporters it's created such as those in >>>> system-taskbar for which a relevant change was made in Tramp recently. I >>>> can take a stab at those. >>>> >>> >>> Here's a patch for progress-reporter. I can look into eglot separately >>> if agreed. >>> >> > Something like this patch should work and it is backward compatible to > Emacs 27. I added a comment about the LSP protocol value range for > percentage and it says we can ignore values outside that range and/or > integer type. Should we? > > diff --git a/lisp/progmodes/eglot.el b/lisp/progmodes/eglot.el > index f701a38ab8b..173a0b87f68 100644 > --- a/lisp/progmodes/eglot.el > +++ b/lisp/progmodes/eglot.el > @@ -2870,9 +2870,17 @@ eglot-handle-notification > (cl-flet ((fmt (&rest args) (mapconcat #'identity args " ")) > (mkpr (title) > (if (eq eglot-report-progress 'messages) > + ;; > https://github.com/microsoft/language-server-protocol/blob/b7f5132c95261c0898ae5124e7a91707abc48fcd/_specifications/specification-3-16.md?plain=1#L1455 > + ;; > + ;; The value range is [0, 100]. > + ;; > + ;; The value should be steadily rising. Clients are > + ;; free to ignore values that are not following this > + ;; rule. > (make-progress-reporter > (format "[eglot] %s %s: %s" > - (eglot-project-nickname server) token title)) > + (eglot-project-nickname server) token title) > + 0 100) > (list 'eglot--mode-line-reporter token title))) > (upd (pcnt msg &optional > (pr (gethash token (eglot--progress-reporters > server)))) > @@ -2880,7 +2888,14 @@ eglot-handle-notification > ((eq (car pr) 'eglot--mode-line-reporter) > (setcdr (cddr pr) (list msg pcnt)) > (force-mode-line-update t)) > - (pr (eglot--reporter-update pr pcnt msg))))) > + (pr (eglot--reporter-update pr pcnt msg)))) > + (done (&optional > + (pr (gethash token (eglot--progress-reporters > server)))) > + (cond > + ((eq (car pr) 'eglot--mode-line-reporter) > + (setcdr (cddr pr) (list "" 100)) > + (force-mode-line-update t)) > + (pr (progress-reporter-done pr))))) > (eglot--dbind ((WorkDoneProgress) kind title percentage message) > value > (pcase kind > ("begin" > @@ -2889,6 +2904,7 @@ eglot-handle-notification > (eglot--progress-reporters server)))) > ("report" (upd percentage message)) > ("end" (upd (or percentage 100) message) > + (done) > (run-at-time 2 nil > (lambda () > (remhash token (eglot--progress-reporters > server)))))))))) >