[clang-tools-extra] [clangd] Fix offset invalid on line. (PR #202267)
Aleksandr Platonov via cfe-commits
cfe-commits at lists.llvm.org
Wed Jun 10 03:17:11 PDT 2026
ArcsinX wrote:
> > Hello @playerC Can you please provide an example scenario when this problem occurs? This example can also be used to write a test.
>
> Hello @ArcsinX
>
> When using Emacs 30.2 with Eglot to write C code, clangd frequently becomes unresponsive after code completion. After adding logging, I discovered that clangd triggers an error and becomes unusable when processing the following scenario:
>
> The clangd client sends a `textDocument/didChange` notification where `end.character` exceeds the length of the corresponding line in clangd's internal document state.
>
> Error log sample:
>
> ```
> V[01:10:18.967] <<< {"jsonrpc":"2.0","method":"textDocument/didChange","params":{"contentChanges":[{"range":{"end":{"character":52,"line":40},"start":{"character":31,"line":40}},"rangeLength":21,"text":"C4MK_FS_PATH_MAX_SIZE ) {\n "}],"textDocument":{"uri":"file:///XXXXXXXXXXXXXX","version":2}}}
>
> I[01:10:18.967] <-- textDocument/didChange
> E[01:10:18.970] Failed to update /XXXXXXXXXXXXXXXXXXXX: utf-8 offset 52 is invalid for line 40
> ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
> V[01:10:18.971] <<< {"id":10,"jsonrpc":"2.0","method":"textDocument/hover","params":{"position":{"character":52,"line":40},"textDocument":{"uri":"file:///XXXXXXXXXXXXXXXX"}}}
>
> I[01:10:18.971] <-- textDocument/hover(10)
> I[01:10:18.971] --> reply:textDocument/hover(10) 0 ms, error: -32602: trying to get AST for non-added document
> V[01:10:18.971] >>> {"error":{"code":-32602,"message":"trying to get AST for non-added document"},"id":10,"jsonrpc":"2.0"}
> ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
> ```
>
> After add some logger code :
>
> ```
> V[00:45:53.497] <<< {"jsonrpc":"2.0","method":"textDocument/didChange","params":{"contentChanges":[{"range":{"end":{"character":52,"line":40},"start":{"character":31,"line":40}},"rangeLength":21,"text":"C4MK_FS_PATH_MAX_SIZE ) {\n "}],"textDocument":{"uri":"file:///XXXXXXXXXXXX","version":28}}}
>
> I[00:45:53.497] <-- textDocument/didChange
> I[00:45:53.497] inside clangd text length: [12], outside clangd text length: [21], inside clangd text: ["C4MK_FS_ ) {"]
> ```
>
> Inside clangd text length: [12], text: [`"C4MK_FS_ ) {"`] , is OK. outside clangd text length: [21], text: [`"C4MK_FS_PATH_MAX_SIZE ) {\n "`], is OK.
>
> But , `end.character` is larger than `start.character` + inside text length.
>
> As you can see, both the text length maintained internally by clangd and the text length in the `didChange` notification are correct. However, an error occurs when the `didChange` attempts to modify the current line to a length greater than its original length.
>
> This change to `didChange` to accept a larger `end.character` , makes text in clangd eventually consistent and simplifies the development of clangd clients, thereby improving stability.
Thanks for clarification.
But it seems that here we are fixing the symptoms, not the root cause. I mean that we need to understand why this happens, maybe this is the problem of the client (if so, clangd is not the right place where we need to fix this)
According to https://microsoft.github.io/language-server-protocol/specifications/lsp/3.18/specification/#textDocument_didChange "Before requesting information from the server (e.g., [textDocument/completion](https://microsoft.github.io/language-server-protocol/specifications/lsp/3.18/specification/#textDocument_completion) or [textDocument/signatureHelp](https://microsoft.github.io/language-server-protocol/specifications/lsp/3.18/specification/#textDocument_signatureHelp)), the client **must** ensure that the document’s state is synchronized with the server to guarantee reliable results."
https://github.com/llvm/llvm-project/pull/202267
More information about the cfe-commits
mailing list