Skip to content

LSP format incorrectly handles files with multi-byte characters #1042

@nojnhuh

Description

@nojnhuh

I observe stylua formatting files differently (to potentially create invalid Lua syntax) through LSP compared to invoking stylua directly on the command line which seems to do the right thing. This seems to only affect files that contain multi-byte unicode characters. Here's a full scenario:

I'm using stylua built from source from the latest main (a456a37).

Given a test.lua file that with these contents:

-- 😕
a = {
  b = {} }

And a .stylua.toml in the same directory:

indent_type = "Spaces"
indent_width = 2

Invoking stylua on the command line makes the correct change:

% stylua -c test.lua                
Diff in test.lua:
1   1    | -- 😕
2   2    | a = {
3        |-  b = {} }
    3    |+  b = {},
    4    |+}

Submitting a textDocument/formatting request to the language server does something different:

3c3
<   b = {} }
---
>   b = {{} }

These are the logs captured by the neovim LSP client:

[DEBUG][2025-10-04 17:01:28] ...m/lsp/client.lua:674	"LSP[stylua]"	"client.request"	1	"textDocument/formatting"	{ options = { insertSpaces = true, tabSize = 2 }, textDocument = { uri = "file:///tmp/stylua/test.lua" } }	<function 1>	1
[DEBUG][2025-10-04 17:01:28] .../vim/lsp/rpc.lua:277	"rpc.send"	{ id = 3, jsonrpc = "2.0", method = "textDocument/formatting", params = { options = { insertSpaces = true, tabSize = 2 }, textDocument = { uri = "file:///tmp/stylua/test.lua" } } }
[DEBUG][2025-10-04 17:01:28] .../vim/lsp/rpc.lua:391	"rpc.receive"	{ id = 3, jsonrpc = "2.0", result = { { newText = " {", range = { ["end"] = { character = 6, line = 2 }, start = { character = 5, line = 2 } } } } }

Replacing the 😕 with o, formatting through LSP makes the same change as the command line invocation, as I'd expect:

3c3,4
<   b = {} }
---
>   b = {},
> }
[DEBUG][2025-10-04 17:03:37] ...m/lsp/client.lua:674	"LSP[stylua]"	"client.request"	1	"textDocument/formatting"	{ options = { insertSpaces = true, tabSize = 2 }, textDocument = { uri = "file:///tmp/stylua/test.lua" } }	<function 1>	1
[DEBUG][2025-10-04 17:03:37] .../vim/lsp/rpc.lua:277	"rpc.send"	{ id = 4, jsonrpc = "2.0", method = "textDocument/formatting", params = { options = { insertSpaces = true, tabSize = 2 }, textDocument = { uri = "file:///tmp/stylua/test.lua" } } }
[DEBUG][2025-10-04 17:03:37] .../vim/lsp/rpc.lua:391	"rpc.receive"	{ id = 4, jsonrpc = "2.0", result = { { newText = ",\n", range = { ["end"] = { character = 9, line = 2 }, start = { character = 8, line = 2 } } } } }

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions