Skip to content
This repository was archived by the owner on Aug 30, 2025. It is now read-only.
This repository was archived by the owner on Aug 30, 2025. It is now read-only.

Crash with invalid String.slice length if file has emoji #865

Description

@nshafer

Dorgan asked me in Discord to report bugs with Lexical, since Expert may have the same problem. This is a weird one I experience in a Phoenix app I'm working on, where when typing just d when I start to type def will crash lexical with:

2025-08-04 12:04:19.717 [info] [Error - 12:04:19 PM] Request textDocument/completion failed.
2025-08-04 12:04:19.717 [info]   Message: ** (FunctionClauseError) no function clause matching in String.slice/3
    (elixir 1.18.3) lib/string.ex:2333: String.slice("  d", 0, -1)
    (lx_common 0.7.2) lib/lexical/code_unit.ex:23: LXical.CodeUnit.utf8_position_to_utf16_offset/2
    (lx_protocol 0.7.2) lib/lexical/protocol/conversions.ex:146: LXical.Protocol.Conversions.extract_lsp_character/1
    (lx_protocol 0.7.2) lib/lexical/protocol/conversions.ex:120: LXical.Protocol.Conversions.to_lsp/1
    (lx_protocol 0.7.2) lib/lexical/protocol/conversions.ex:98: LXical.Protocol.Conversions.to_lsp/1
    (lx_protocol 0.7.2) lib/lexical/protocol/convertibles/lexical.document.edit.ex:11: LXical.Convertible.Lexical.Document.Edit.to_lsp/1
    (lx_lexical_shared 0.5.0) lib/lexical/convertible.ex:9: anonymous fn/3 in LXical.Convertible.Helpers.apply/2
    (elixir 1.18.3) lib/enum.ex:4968: Enumerable.List.reduce/3

  Code: -32603 

I was able to reproduce this in a new project created with mix phx.new lxtest (1.8.0-rc.4). After install and dep install/compile so everything is happy, in VS Code, create a new file, "lib/testlx_web/components/test_component.ex" and paste:

defmodule TestlxWeb.Components.TestComponent do
  use TestlxWeb, :live_component

  def render(assigns) do
    ~H"""
    <div>
      <h1>Hello, {@name}! ⚠️</h1>
    </div>
    """
  end
end

Now try to create a new function, as soon as you type d it will crash. If you remove the emoji, then it works as expected. I'm guessing this is due to counting codepoints instead of graphemes, as that emoji is 2 codepoints.

iex(6)> s = "Hello⚠️"
"Hello⚠️"
iex(7)> s
"Hello⚠️"
iex(8)> String.codepoints(s)
["H", "e", "l", "l", "o", "⚠", ""]
iex(9)> String.graphemes(s)
["H", "e", "l", "l", "o", "⚠"]

Thanks!

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions