Skip to content

fix: unhandled incoming frames before websocket connection is established#6

Open
maslowalex wants to merge 4 commits into
bunopnu:mainfrom
maslowalex:fix-add-frames-buffer
Open

fix: unhandled incoming frames before websocket connection is established#6
maslowalex wants to merge 4 commits into
bunopnu:mainfrom
maslowalex:fix-add-frames-buffer

Conversation

@maslowalex

@maslowalex maslowalex commented Nov 25, 2025

Copy link
Copy Markdown

This pull request is an attempt to fix currently unhandled scenario when we have incoming frames before the Websocket connection is being established.

The error stacktrace:

[error] 21:52:29.761  :gen_statem #PID<0.629.0> terminating
** (BadMapError) expected a map, got:

    nil

    (mint_web_socket 1.0.4) lib/mint/web_socket/frame.ex:103: Mint.WebSocket.Frame.encode/2
    (fresh 0.4.4) lib/fresh/connection.ex:221: Fresh.Connection.send_frame/2
    (elixir 1.19.2) lib/enum.ex:2520: Enum."-reduce/3-lists^foldl/2-0-"/3
    (fresh 0.4.4) lib/fresh/connection.ex:280: Fresh.Connection.handle_generic_callback/2
    (fresh 0.4.4) lib/fresh/connection.ex:139: Fresh.Connection.connected/3
    (stdlib 7.1) gen_statem.erl:3748: :gen_statem.loop_state_callback/11
    (stdlib 7.1) proc_lib.erl:333: :proc_lib.init_p_do_apply/3
Queue: [info: {:subscribe_candles, ["5m"]}]
Postponed: []

@maslowalex maslowalex changed the title fix: unhandled incomming frames before websocket connection is established fix: unhandled incoming frames before websocket connection is established Nov 25, 2025
maslowalex and others added 3 commits December 9, 2025 13:47
reconnect/1 rebuilt the connection struct but omitted frame_queue,
leaving it nil (its defstruct default). A frame queued before the new
websocket handshake completed (e.g. an application-level ping firing in
the connected-but-not-yet-handshaked window) prepended onto nil,
producing an improper list [frame | nil]. The :done flush then ran
Enum.reverse/1 over it and crashed (FunctionClauseError / ArgumentError
"not a proper list"), killing the connection process.

Reset frame_queue to [] in the reconnect rebuild, matching response_queue
and init/1, so the queue is always a proper list.

Adds a regression test: a /slow_websocket route widens the handshake
window so pings deterministically queue during a reconnect; the client
must survive the flush and keep serving traffic.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
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

Successfully merging this pull request may close these issues.

1 participant