Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

stdio buffer exception #299

Open
AHBruns opened this issue Oct 23, 2023 · 16 comments
Open

stdio buffer exception #299

AHBruns opened this issue Oct 23, 2023 · 16 comments

Comments

@AHBruns
Copy link

AHBruns commented Oct 23, 2023

17:45:12.329 [error] Task #PID<0.355.0> started from NextLS.Buffer terminating
** (MatchError) no match of right hand side value: [",\\n    \\\"address\\\",\\n    \\\"street_address_line_2\\\",\\n    \\\"city\\\",\\n    \\\"state\\\",\\n    \\\"zip\\\"\\n  ]\\n\\n  @impl Oban.Worker\\n  def perform(%Oban.Job{args", " %{\\\"portal_id\\\" => _portal_id, \\\"contact_id\\\" => contact_id}}) do\\n    case Contact.get_contact_properties(", "lead_ranking, contact_id, @lead_ranking_properties) do\\n      {", "ok, ", "archived} ->\\n        ", "ok\\n\\n      {", "ok, properties} ->\\n        plan_for(\\n          rankability(properties[\\\"hs_lead_status\\\"]),\\n          nillify(properties[\\\"lead_rank\\\"]),\\n          nillify(properties[\\\"zip\\\"])\\n        ).(contact_id, properties)\\n\\n      error ->\\n        error\\n    end\\n  end\\n\\n  defp plan_for(_status, nil, nil), do", " &nothing/2\\n  defp plan_for(", "rankable, nil, _zip), do", " &create_lead_rank/2\\n  defp plan_for(", "unrankable, nil, _zip), do", " &nothing/2\\n  defp plan_for(_status, _lead_rank, nil), do", " &clear_lead_rank/2\\n  defp plan_for(", "rankable, _lead_rank, _zip), do", " &update_lead_rank/2\\n  defp plan_for(", "unrankable, _lead_rank, _zip), do", " &clear_lead_rank/2\\n\\n  defp nothing(_contact_id, _properties), do", " ", "ok\\n\\n  defp create_lead_rank(contact_id, properties) do\\n    set_lead_rank(contact_id, rank_for(properties))\\n  end\\n\\n  defp update_lead_rank(contact_id, %{\\\"lead_rank\\\" => lead_rank} = properties) do\\n    case rank_for(properties) do\\n      ^lead_rank -> ", "ok\\n      new_lead_rank -> set_lead_rank(contact_id, new_lead_rank)\\n    end\\n  end\\n\\n  defp clear_lead_rank(contact_id, _properties) do\\n    set_lead_rank(contact_id, \\\"\\\")\\n  end\\n\\n  defp rank_for(%{\\n         \\\"address\\\" => address,\\n         \\\"street_address_line_2\\\" => street_address_line_2,\\n         \\\"city\\\" => city,\\n         \\\"state\\\" => state,\\n         \\\"zip\\\" => zip\\n       }) do\\n    {", "ok, %{\\\"total_available_therapists\\\" => total_available_therapists}} =\\n      Serviceability.available_therapists(%{\\n        address_text", "\\n          [\\n            address,\\n            street_address_line_2,\\n            city,\\n            state,\\n            zip\\n          ]\\n          |> Enum.filter(fn\\n            nil -> false\\n            \\\"\\\" -> false\\n            _otherwise -> true\\n          end)\\n          |> Enum.join(\\\", \\\")\\n      })\\n\\n    Integer.to_string(total_available_therapists)\\n  end\\n\\n  defp set_lead_rank(contact_id, value) do\\n    Contact.set_contact_properties(", "lead_ranking, contact_id, %{\\\"lead_rank\\\" => value})\\n  end\\n\\n  defp nillify(\\\"\\\"), do", " nil\\n  defp nillify(nil), do", " nil\\n  defp nillify(value), do", " value\\n\\n  defp rankability(\\\"Patient - Suspect\\\"), do", " ", "rankable\\n  defp rankability(\\\"Patient - Qualified", " Ready to book\\\"), do", " ", "rankable\\n  defp rankability(_value), do", " ", "unrankable\\nend\\n\"}}}Content-Length", " 201"]
    (gen_lsp 0.6.0) lib/gen_lsp/communication/stdio.ex:73: GenLSP.Communication.Stdio.read_header/1
    (gen_lsp 0.6.0) lib/gen_lsp/communication/stdio.ex:40: GenLSP.Communication.Stdio.read/2
    (gen_lsp 0.6.0) lib/gen_lsp/buffer.ex:128: anonymous fn/4 in GenLSP.Buffer.read/2
    (elixir 1.15.5) lib/stream.ex:1626: Stream.do_resource/5
    (elixir 1.15.5) lib/enum.ex:4387: Enum.reverse/1
    (elixir 1.15.5) lib/enum.ex:3704: Enum.to_list/1
    (elixir 1.15.5) lib/task/supervised.ex:101: Task.Supervised.invoke_mfa/2
Function: #Function<0.64901786/0 in GenLSP.Buffer.read/2>
    Args: []

This is the error in the logs. It seems to be specific to files using Oban.

@AHBruns
Copy link
Author

AHBruns commented Oct 23, 2023

I take it back, it's not just Oban related files.

@mhanberg
Copy link
Collaborator

Can you give me the exact contents of the file that causes this?

You can email it to me if it's sensitive, but it's already error you pasted.

@AHBruns
Copy link
Author

AHBruns commented Oct 24, 2023

defmodule Grimoire.PatientCentricSearch.LiteHubspotContactsSyncChunkWorker do
  @moduledoc false

  use Oban.Pro.Workers.Chunk,
    queue: :hubspot_requesters,
    by: [args: :profile],
    size: 100,
    timeout: 1000

  alias Grimoire.Bridges.Hubspot.Api.Contact
  alias Grimoire.PatientCentricSearch.LiteHubspotContact
  alias Grimoire.Repo

  require Logger

  @impl true
  def process([%{args: %{"profile" => profile}} | _] = jobs) do
    results =
      profile
      |> String.to_existing_atom()
      |> Contact.batch_get_contact_properties(
        jobs
        |> Stream.map(fn job ->
          Map.fetch!(job.args, "hs_object_id")
        end)
        |> Stream.uniq(),
        [
          "firstname",
          "middle_name",
          "lastname",
          "date_of_birth",
          "email",
          "address",
          "phone"
        ]
      )

    Enum.each(results, fn
      {hs_object_id, {:ok, :archived}} ->
        Repo.delete!(
          %LiteHubspotContact{hs_object_id: hs_object_id},
          stale_error_field: :hs_object_id,
          stale_error_message: "is already deleted"
        )

      {hs_object_id, {:ok, contact}} ->
        properties = [
          first_name: contact["firstname"],
          middle_name: contact["middle_name"],
          last_name: contact["lastname"],
          date_of_birth: contact["date_of_birth"],
          email: contact["email"],
          address: contact["address"],
          phone: contact["phone"],
          hs_object_id: hs_object_id
        ]

        # upsert
        Repo.insert!(
          struct!(LiteHubspotContact, properties),
          on_conflict: [set: properties],
          conflict_target: :hs_object_id
        )

      {hs_object_id, {:error, reason}} ->
        Logger.error("an error was returned when attempting to read hubspot contact #{hs_object_id}: #{inspect(reason)}")
    end)

    failed_jobs =
      Enum.filter(jobs, fn %{args: %{"hs_object_id" => hs_object_id}} ->
        case results[hs_object_id] do
          {:ok, _} -> false
          _ -> true
        end
      end)

    if Enum.empty?(failed_jobs) do
      :ok
    else
      {:error, "failed to sync", failed_jobs}
    end
  end
end

It's not particularly sensitive. Blowing away _build and .elixir-tools does seems to have fixed the issue fwiw.

@mhanberg
Copy link
Collaborator

Also what is your elixir and otp versions and what is your OS

@mhanberg
Copy link
Collaborator

Are there any files that might have strange Unicode characters in them?

@AHBruns
Copy link
Author

AHBruns commented Oct 24, 2023

Nothing comes to mind with strange unicode characters. Also, after blowing everything away it did start happening again, thought this time with a different error (different file, btw):

19:47:39.727 [error] GenServer NextLS.Buffer terminating
** (Jason.DecodeError) unexpected end of input at position 2988
    (jason 1.4.1) lib/jason.ex:92: Jason.decode!/2
    (gen_lsp 0.6.0) lib/gen_lsp/buffer.ex:82: GenLSP.Buffer.handle_cast/2
    (stdlib 5.0.2) gen_server.erl:1103: :gen_server.try_handle_cast/3
    (stdlib 5.0.2) gen_server.erl:1165: :gen_server.handle_msg/6
    (stdlib 5.0.2) proc_lib.erl:241: :proc_lib.init_p_do_apply/3
Last message: {:"$gen_cast", {:incoming, "\n{\"jsonrpc\":\"2.0\",\"method\":\"textDocument/didSave\",\"params\":{\"textDocument\":{\"uri\":\"file:///Users/alexbruns/code/luna/grimoire/lib/grimoire_web/live/patient_centric_search/search_bar.ex\"},\"text\":\"defmodule GrimoireWeb.PatientCentricSearchLive.SearchBar do\\n  @moduledoc false\\n\\n  use GrimoireWeb, :live_component\\n\\n  alias Grimoire.PatientCentricSearch\\n  alias GrimoireWeb.OmniUI\\n\\n  def search_bar(assigns) do\\n    ~H\\\"\\\"\\\"\\n    <.live_component module={__MODULE__} {assigns} />\\n    \\\"\\\"\\\"\\n  end\\n\\n  @impl true\\n  def render(assigns) do\\n    ~H\\\"\\\"\\\"\\n    <div>\\n      <.form for={@form} phx-target={@myself} phx-change=\\\"search\\\" phx-debounce={300}>\\n        <OmniUI.text_input field={{@form, :query}} placeholder=\\\"Search for a patient...\\\" />\\n      </.form>\\n    </div>\\n    \\\"\\\"\\\"\\n  end\\n\\n  @impl true\\n  def mount(socket) do\\n    {:ok, initialize_assigns(socket)}\\n  end\\n\\n  @impl true\\n  def update(assigns, socket) do\\n    {\\n      :ok,\\n      socket\\n      |> update_params(assigns.params)\\n      |> update_id(assigns.id)\\n    }\\n  end\\n\\n  @impl true\\n  def handle_event(\\\"search\\\", params, socket) do\\n    {:noreply, update_query(socket, params[\\\"form\\\"][\\\"query\\\"])}\\n  end\\n\\n  defp update_id(socket, new_id) do\\n    if socket.assigns.id != new_id do\\n      socket\\n      |> assign(:id, new_id)\\n      |> update_query(Map.get(socket.assigns.params, new_id, \\\"\\\"))\\n    else\\n      socket\\n    end\\n  end\\n\\n  defp initialize_assigns(socket) do\\n    socket\\n    |> assign(:id, nil)\\n    |> assign(:params, %{})\\n    |> assign(:query, \\\"\\\")\\n    |> assign(:form, form_from_query(\\\"\\\"))\\n  end\\n\\n  defp form_from_query(query) do\\n    to_form(%{\\\"query\\\" => query}, as: :form)\\n  end\\n\\n  defp update_params(socket, params) do\\n    if socket.assigns.params != params do\\n      socket\\n      |> assign(:params, params)\\n      |> update_query(Map.get(params, socket.assigns.id, \\\"\\\"))\\n    else\\n      socket\\n    end\\n  end\\n\\n  defp update_query(socket, query) do\\n    if socket.assigns.query != query do\\n      query\\n      |> PatientCentricSearch.search()\\n      |> emit_search_results()\\n\\n      socket\\n      |> assign(:query, query)\\n      |> update_form(form_from_query(query))\\n      |> sync_to_url()\\n    else\\n      socket\\n    end\\n  end\\n\\n  defp emit_search_results(search_results) do\\n    topic = \\\"patient_centric_search_live:\#{inspect(self())}\\\"\\n    Phoenix.PubSub.broadcast(Grimoire.PubSub, topic, {topic, :search_results, search_results})\\n  end\\n\\n  defp update_form(socket, new_form) do\\n    if socket.assigns.form != new_form do\\n      assign(socket, :form, new_form)\\n    else\\n      socket\\n    end\\n  end\\n\\n  defp sync_to_url(socket) do\\n    if Map.get(socket.assigns.params, socket.assigns.id, \\\"\\\") != socket.assigns.query do\\n      new_params = Map.put(socket.assigns.params, socket.assigns.id, socket.assigns.query)\\n      push_patch(socket, to: ~p\\\"/patient-centric-search?\#{new_params}\\\")\\n    else\\n      socket\\n    end\\n  end\\nend\\n\"}"}}
State: %{lsp: #PID<0.193.0>, comm: GenLSP.Communication.Stdio, comm_data: nil, awaiting_response: %{}}

Wrt versions:

Erlang/OTP 26 [erts-14.0.2] [source] [64-bit] [smp:10:10] [ds:10:10:10] [async-threads:1] [jit] [dtrace]

Elixir 1.15.7 (compiled with Erlang/OTP 26)

I'm on a mac.

@mhanberg
Copy link
Collaborator

What editor?

@mhanberg
Copy link
Collaborator

I'm finishing up some better debugging tools so hopefully after I release that you can update and this will become easier to track down.

@mhanberg
Copy link
Collaborator

Assuming I don't figure it out earlier

@AHBruns
Copy link
Author

AHBruns commented Oct 24, 2023

vs code

@crbelaus
Copy link
Contributor

I've been noticing this from time to time as well. Didn't open an issue yet because I cannot find a reliable way of reproducing it as it gets fixed when deleting the .elixir-tools folder and restarting the editor as @AHBruns says.

Will keep an eye on it and post a comment if I see it happening again.

@mhanberg mhanberg changed the title When I save a file formatting hangs stdio buffer exception Oct 24, 2023
@mhanberg
Copy link
Collaborator

mhanberg commented Oct 24, 2023

Since this is a GenLSP issue, I opened an issue over there. Will leave this one open tho as well to track it until I fix and update

elixir-tools/gen_lsp#41

@mhanberg
Copy link
Collaborator

mhanberg commented Nov 4, 2023

I am having trouble reproducing this with a property test, but @fhunleth says he was seeing similar errors after seeing another error that he submitted a patch (#331) for.

I will keep this open, but after I release this patch on v0.15, please let me know if you continue to see errors like this.

Thanks!

@PJUllrich
Copy link

Hey folks, just wanted to note that I'm running into this issue maybe every 2 hours now. It happens when NextLS compiles my dependencies (I don't know why it does that though because I haven't changed my dependencies in a few days). This prevents my editor (VSCode) from saving the file, which is blocking me from coding. I usually just restart my VSCode and then the error goes away.

I'll just drop the full output here in the hope that you find an error.

[NextLS] Unchecked dependencies for environment dev:
* bcrypt_elixir (Hex package)
[NextLS]   the dependency is not available, run "mix deps.get"
# </------ 50 other dependencies with the same error message ---------->
[Warn  - 20:03:56] [NextLS] Unexpected compiler response: {:error, %{message: "Can't continue due to errors on dependencies", __struct__: Mix.Error, __exception__: true, mix: 1}}
[Error - 20:05:10] ** (SyntaxError) nofile:44:7: keyword argument must be followed by space after: https:
    |
 44 |       some compile error here # <- I forgot a comma after a field in a map
    |       ^

[NextLS] Unchecked dependencies for environment dev:
* bcrypt_elixir (Hex package)
[NextLS]   the dependency is not available, run "mix deps.get"
# </------ 50 other dependencies with the same error message ---------->
[Warn  - 20:05:16] [NextLS] Unexpected compiler response: {:error, %{message: "Can't continue due to errors on dependencies", __struct__: Mix.Error, __exception__: true, mix: 1}}

[NextLS]   the dependency is not available, run "mix deps.get"
# </------ 50 other dependencies with the same error message ---------->
[Warn  - 20:05:25] [NextLS] Unexpected compiler response: {:error, %{message: "Can't continue due to errors on dependencies", __struct__: Mix.Error, __exception__: true, mix: 1}}

20:05:43.117 [error] GenServer NextLS.Buffer terminating
** (Jason.DecodeError) unexpected end of input at position 258
    (jason 1.4.1) lib/jason.ex:92: Jason.decode!/2
    (gen_lsp 0.6.2) lib/gen_lsp/buffer.ex:82: GenLSP.Buffer.handle_cast/2
    (stdlib 5.1.1) gen_server.erl:1103: :gen_server.try_handle_cast/3
    (stdlib 5.1.1) gen_server.erl:1165: :gen_server.handle_msg/6
    (stdlib 5.1.1) proc_lib.erl:241: :proc_lib.init_p_do_apply/3
Last message: {:"$gen_cast", {:incoming, "\n{\"jsonrpc\":\"2.0\",\"id\":2296,\"method\":\"textDocument/completion\",\"params\":{\"textDocument\":{\"uri\":\"file:///Users/peterullrich/Development/vcp/lib/app_web/live/some_path_and_live_view.ex\"},\"position\":{\"line\":39,\"character\":23},\"context\":{\"triggerKind\":1}}"}}
State: %{lsp: #PID<0.193.0>, comm: GenLSP.Communication.Stdio, comm_data: nil, awaiting_response: %{}}

@mhanberg
Copy link
Collaborator

mhanberg commented Dec 8, 2023

@PJUllrich thank you! And sorry it's happening so frequently.

I'm starting to think this might be a VScode thing, as I haven't ever run into this personally (in neovim).

I'll have to run VSCode for a day to see if I can reproduce.

@PJUllrich
Copy link

No worries :) all the more reason to finally switch to Neovim maybe 😬

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants