       {:ok, socket} ->
         state = %{state | socket: socket}
         {:ok, shared_state} = SharedState.start_link()
-        receiver = start_receiver_and_hand_socket(state.socket, shared_state)
-        state = %{state | shared_state: shared_state, receiver: receiver}
-        {:ok, state}
+        case start_receiver_and_hand_socket(state.socket, shared_state) do
+          {:ok, receiver} ->
+            state = %{state | shared_state: shared_state, receiver: receiver}
+            {:ok, state}
+          {:error, reason} ->
+            {:stop, %ConnectionError{reason: reason}}
+        end
       {error_or_stop, reason} when error_or_stop in [:error, :stop] ->
         {:stop, %ConnectionError{reason: reason}}
     end

      {:ok, socket} ->
        state = %{state | socket: socket}
        {:ok, shared_state} = SharedState.start_link()
        receiver = start_receiver_and_hand_socket(state.socket, shared_state)

        # If this is a reconnection attempt, log that we successfully
        # reconnected.
        if info == :backoff do
          log(state, :reconnection, ["Reconnected to Redis (", Utils.format_host(state), ?)])
        end

        state = %{state | shared_state: shared_state, receiver: receiver}
        {:ok, state}
      {:error, reason} ->
        log state, :failed_connection, [
          "Failed to connect to Redis (", Utils.format_host(state), "): ",


  defp start_receiver_and_hand_socket(socket, shared_state) do
    {:ok, receiver} = Receiver.start_link(sender: self(), socket: socket, shared_state: shared_state)
    with :ok <- :gen_tcp.controlling_process(socket, receiver),
         do: {:ok, receiver}
  end

  defp flush_messages_from_receiver(%{receiver: receiver} = state) do
