Skip to content

formatter lsp: LSP formatting of special characters generates invalid results #23314

Description

@nrayburn-tech

Initially reported in oxc-project/oxc-intellij-plugin#502, but I was able to confirm odd behavior with IntelliJ and VS Code. This does not apply with the Oxc playground or CLI, so it's pretty likely a language server issue or something odd the language server is doing when interacting with the formatter.

  1. Clone https://github.com/nrayburn-tech/oxc-intellij-plugin-502
  2. Run npm install
  3. Trigger formatting through the language server.
  4. Content output is malformed.

On line 5, there is a trailing space. It seems like if this is removed before formatting, the output isn't malformed. So maybe that's relevant.

Input (may need to grab from pastebin https://pastebin.com/raw/F0ymMpWR, I had issues reproducting when copying it from GitHub directly)

describe('strformat', () => {
  test('Those symbols break oxfmt plugin completely:', () => {
    expect(strformat('[{x}]', true, { x: 'a
b' })).toBe('[a\\u2028b]')
    expect(strformat('[{x}]', true, { x: 'a
b' })).toBe('[a\\u2029b]')
  }) 

  test('xyz', () => {})
})

Output

describe('strformat', () => {
  test('Those symbols break oxfmt plugin completely:', () => {
    expect(strformat('[{x}]', true, { x: 'a
b' })).toBe('[a\\u2028b]')
    expect(strformat('[{x}]', true, { x: 'a
b' })).toBe('[a\\u2029b]')
  }) 

  te

  test('xyz', () => {})
})

VS Code output for opening the file and formatting it.

Details
2026-06-11 22:26:57.630 [info] [Trace - 10:26:57 PM] Sending notification 'textDocument/didOpen'.
2026-06-11 22:26:57.630 [info] Params: {
    "textDocument": {
        "uri": "file:///Users/nrayburn/Documents/github/oxc-project/reproductions/oxc-intellij-plugin-502/test.js",
        "languageId": "javascript",
        "version": 238,
        "text": "describe('strformat', () => {\n  test('Those symbols break oxfmt plugin completely:', () => {\n    expect(strformat('[{x}]', true, { x: 'a
b' })).toBe('[a\\\\u2028b]')\n    expect(strformat('[{x}]', true, { x: 'a
b' })).toBe('[a\\\\u2029b]')\n  }) \n\n  test('xyz', () => {})\n})"
    }
}


2026-06-11 22:27:00.746 [info] [Trace - 10:27:00 PM] Sending request 'textDocument/formatting - (46)'.
2026-06-11 22:27:00.746 [info] Params: {
    "textDocument": {
        "uri": "file:///Users/nrayburn/Documents/github/oxc-project/reproductions/oxc-intellij-plugin-502/test.js"
    },
    "options": {
        "tabSize": 2,
        "insertSpaces": true
    }
}


2026-06-11 22:27:00.747 [info] [Trace - 10:27:00 PM] Received response 'textDocument/formatting - (46)' in 1ms.
2026-06-11 22:27:00.747 [info] Result: [
    {
        "range": {
            "start": {
                "line": 6,
                "character": 4
            },
            "end": {
                "line": 9,
                "character": 2
            }
        },
        "newText": "\n\n  test('xyz', () => {})\n})\n"
    }
]


2026-06-11 22:27:01.003 [info] [Trace - 10:27:01 PM] Sending notification 'textDocument/didChange'.
2026-06-11 22:27:01.003 [info] Params: {
    "textDocument": {
        "uri": "file:///Users/nrayburn/Documents/github/oxc-project/reproductions/oxc-intellij-plugin-502/test.js",
        "version": 239
    },
    "contentChanges": [
        {
            "text": "describe('strformat', () => {\n  test('Those symbols break oxfmt plugin completely:', () => {\n    expect(strformat('[{x}]', true, { x: 'a
b' })).toBe('[a\\\\u2028b]')\n    expect(strformat('[{x}]', true, { x: 'a
b' })).toBe('[a\\\\u2029b]')\n  }) \n\n  te\n\n  test('xyz', () => {})\n})\n"
        }
    ]
}

FYI @leaysgur @Sysix

Metadata

Metadata

Assignees

No one assigned

    Labels

    A-editorArea - Editor and Language Server

    Type

    Fields

    Priority

    None yet

    Effort

    None yet

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions