File.cp! to destination with extension in name in consume_uploaded_entries causes all sockets to refresh?

I am trying to figure out why a File.cp! to only a destination with an extension in the name is causing a socket somewhere to refresh. The refresh doesn’t happen if I don’t include the extension in the File.cp!. Here is the relevant code:

  defp consume_files(socket) do
    consume_uploaded_entries(socket, :image, fn params, entry ->
      path = params[:path]

      extname = List.last(String.split(entry.client_name, "."))
      filename = Path.basename(path) <> "." <> extname

      dest =

      # refresh doesn't happen if you comment the following out:
      # dest =
      #   Path.join([
      #     :code.priv_dir(:app),
      #     "static",
      #     "uploads",
      #     Path.basename(path)
      #   ])

      # This line causes a refresh ------------------------------------------------------------------
      result = File.cp!(path, dest)
      # /This line causes a refresh -----------------------------------------------------------------

      {:postpone, ~p"/uploads/#{filename}"}

Going off the code you posted, isn’t the refresh happening when you are not including the extension and working as expected when you are including the extension?

Regardless, one way or the other File.cp!/3 will raise an exception when it fails, which would cause all sockets to restart/refresh.

cp!(source_file, destination_file, callback \ fn _, _ → true end)

The same as cp/3, but raises a File.CopyError exception if it fails. Returns :ok otherwise.

source: File.cp!/3 docs

In general, the ! at the end of a function indicates that the function will raise an exception when it fails whereas the non-! version of a function will not.

1 Like

I have confirmed that with MIX_ENV=prod, the refresh does not happen. I seem to recall that dev LiveView does some magic with refreshes, doesn’t it? I think that may be the issue, but I can’t seem to find where that is documented.

Thanks for the help, but I think this is the result of LiveView in dev refreshing things that it wouldn’t in production. See my previous response for more.

Ah, you didn’t specify what location it is, perhaps the location you’re copying it to is triggering the dev code reloader?


I think the issue can be found in config/dev.exs:

# Watch static and templates for browser reloading.
config :app, AppWeb.Endpoint,
  live_reload: [
    patterns: [

Since I am copying images, the first regex would match.