rhcarvalho

rhcarvalho

Handling Channels/LiveView LongPoll fallback "unmatched topic"

I’m investigating LiveView JS client errors when the Socket/LiveSocket throws failed with reason: {"reason":"unmatched topic"}.

I modified Phoenix 1.8.1 to emit telemetry events when the “unmatched topic” condition happens server side and collected some of those events (including socket and reply) with production traffic for debugging.

It turns out a batch of such errors all were related to the :longpoll transport and I’m trying to understand what the underlying cause might be, and whether I can safely ignore those errors assuming the channel connection will be re-established anyway later.

I have a proxy (Cloudflare) between users and the server.

This is one of the events, PII scrubbed:

%{
  name: [:phoenix, :socket_unmatched_topic],
  metadata: %{
    reply: %Phoenix.Socket.Reply{
      topic: "lv:phx-GGJYSitVRluvhDWD",
      status: :error,
      payload: %{reason: "unmatched topic"},
      ref: "92",
      join_ref: nil
    },
    socket: %Phoenix.Socket{
      assigns: %{},
      channel: nil,
      channel_pid: nil,
      endpoint: MyAppWeb.Endpoint,
      handler: Phoenix.LiveView.Socket,
      id: nil,
      joined: false,
      join_ref: nil,
      private: %{
        connect_info: %{
          x_headers: [
            # ...
          ]
        }
      },
      pubsub_server: MyApp.PubSub,
      ref: nil,
      serializer: Phoenix.Socket.V2.JSONSerializer,
      topic: nil,
      transport: :longpoll,
      transport_pid: #PID<0.33718.0>
    }
  },
  measurements: %{system_time: 1757064975931223300}
}

Has anybody explored this area before and could help shed some light?
What additional data could I gather?

My current thought is that the client either misses a ping/heartbeat or the proxy terminates a connection earlier, causing a server process backing the channel connection to go away. Probably the client reconnects spawning a new process / "lv:..." topic and the user doesn’t even notice :crossed_fingers:

It would help me to reproduce this locally, so any tips / shortcuts are welcome :slight_smile:

Marked As Solved

Also Liked

steffend

steffend

Phoenix Core Team

I was able to reproduce. Will investigate!

steffend

steffend

Phoenix Core Team

Thank you for reporting. That issue was in the code basically since forever, so it’s interesting that this doesn’t seem to have happened very frequently in the past. I hope we’ll get a new Phoenix version out this week!

rhcarvalho

rhcarvalho

Closing the loop in case anyone finds this in the future:

The “unmatched topic” error is a race condition that can happen when the client tries to push an event to a topic the server doesn’t know about (e.g. because the LiveView process is gone).

The pushEvent JS hook method has two possible signatures: pushEvent(name, payload, onReply): void and pushEvent(name, payload): Promise, the former silently ignores errors while the later rejects the promise instead.

I was using the promise-based version for a fire-and-forget event and needed to properly ignore the event on my application’s side.

The LiveView docs has been updated to document the behavior of pushEvent and pushEventTo.

https://github.com/phoenixframework/phoenix_live_view/pull/4220

Thanks @steffend for your help!

Last Post!

rhcarvalho

rhcarvalho

Closing the loop in case anyone finds this in the future:

The “unmatched topic” error is a race condition that can happen when the client tries to push an event to a topic the server doesn’t know about (e.g. because the LiveView process is gone).

The pushEvent JS hook method has two possible signatures: pushEvent(name, payload, onReply): void and pushEvent(name, payload): Promise, the former silently ignores errors while the later rejects the promise instead.

I was using the promise-based version for a fire-and-forget event and needed to properly ignore the event on my application’s side.

The LiveView docs has been updated to document the behavior of pushEvent and pushEventTo.

https://github.com/phoenixframework/phoenix_live_view/pull/4220

Thanks @steffend for your help!

Where Next?

Popular in Questions Top

baxterw3b
Hi guys, i’m new in the Elixir world, and i have to say, that i love it! i’m having some problem to understand anonymous functions with ...
New
jononomo
I am trying to figure out how Mix knows whether the environment is test, dev, or prod – where is this set? Thanks.
New
New
hariharasudhan94
Lets say I have map like this fetching from my database %{"_id" =&gt; #BSON.ObjectId&lt;58eb1a7a9ad169198c3dXXXX&gt;, "email" =&gt; ...
New
komlanvi
Hi everyone, I was playing with phoenix liveView but I run into an issue. I have a form and want to validate each input text when the te...
New
dblack
I’ve got an issue with an app and I’ve no idea of how to troubleshoot it. I’m hoping someone here might have seen something similar. I p...
New
romenigld
I am trying to run a deploy with docker and I successfully runned with this command: docker build -t romenigld/blog-prod . but when I t...
New

Other popular topics Top

rms.mrcs
Hi, I need to transform a list of numbers into a map where the keys are the indexes and the values are the original values of the list. ...
New
JakeBecker
TL;DR: I’ve just released an implementation of Microsoft’s IDE-independent Language Server Protocol for Elixir. It adds language support ...
1144 54921 245
New
jononomo
For some reason my phoenix channels are working for me in my local dev environment, but as soon as I deploy via Docker, I get a 403 error...
New
greenz1
I have a phoenix application from which a user can download multiple(5-6) files of size 1MB. I couldn’t find anything related to sending ...
New
bsollish-terakeet
Credo is smart enough to check for (something like) this: assert length(the_list) == 0 with this response: Checking if an enum is empt...
New
TunkShif
This post is an instruction guide to help you setup your Neovim for Elixir development from scratch. It includes general information on h...
274 42533 114
New

We're in Beta

About us Mission Statement