Receiving unexpected exception with File.cp

Hi all,

I’m wrapping File.cp in case, but I’m never getting to the {:error, reason} clause even though there is an error.

Here’s the code:

76: defp copy_file(from_path, to_path) do
77:   case File.exists?(from_path) do
78:      true ->
79:        case File.cp(from_path, to_path) do
80:          :ok ->
81:            Logger.info("Copied #{from_path} to #{to_path}")
82:
83:          {:error, reason} ->
84:            Logger.error("Unable to copy #{from_path} to #{to_path} because: #{inspect(reason)}")
85:
86:     false ->
87:        Logger.error("Unable to copy #{from_path} because it does not exist at this time.")
88:    end
89: end

Here’s the error I’m getting:

17:39:13.677 [info] Received new file at: /tmp/.file67.txt.  Copying to temp_loc.
17:39:13.678 [error] GenServer {FileRegistry, ".file67.txt"} terminating
** (File.Error) could not read file stats "/tmp/.file67.txt": no such file or directory
    (elixir 1.14.0) lib/file.ex:408: File.stat!/2
    (elixir 1.14.0) lib/file.ex:1006: File.copy_file_mode!/2
    (elixir 1.14.0) lib/file.ex:1013: File.do_cp_file/4
    (elixir 1.14.0) lib/file.ex:815: File.cp/3
    (ram_disk_daemon 0.1.0) lib/file_mover/file_mover.ex:79: FileMover.FileMover.copy_file/2
    (ram_disk_daemon 0.1.0) lib/file_mover/file_mover.ex:49: FileMover.FileMover.handle_cast/2
    (stdlib 4.0.1) gen_server.erl:1120: :gen_server.try_dispatch/4
    (stdlib 4.0.1) gen_server.erl:1197: :gen_server.handle_msg/6
Last message: {:"$gen_cast", {:new_file, "/tmp/.file67.txt"}}
State: "/tmp/.file67.txt"

Notice that it’s on line 79, which is calling File.cp and not File.cp!, which should return {:error, reason}, but instead it looks like an exception is being raised.

I shouldn’t expect to get an exception here, right?

What version of elixir are you using?

Elixir v1.14.0 / Erlang 25.0.4

1 Like

This seems to be an Elixir bug,
I’ve checked the sources and indeed, it calls the raising stat! function. I think you can create an issue in elixir repo

But I think there’s also some problem in your code, because file disappears right after it was copied into the /tmp

That’s on purpose, kind of. I’m writing a service that copies files to persistent storage as they come in from another service. In this case, one service delivers a file (lets say FTP) with the file name ".filename", and then immediately renames it to "filename". My Elixir service is failing because it’s trying to copy the ".filename"and sometimes in the middle of that copy the rename happens.

I’ve already fixed my logic to ignore the .filename, but it still unmasked a bug within File.cp.

I’ve written a bug here: Receiving unexpected exception from File.cp · Issue #12145 · elixir-lang/elixir (github.com)

And submitted a pull request here: Removes calls to exception raising functions in cp by jeramyRR · Pull Request #12146 · elixir-lang/elixir (github.com)

1 Like

Woot Woot, my PR for the fix was merged by Jose today! That’s my first PR to Elixir.

2 Likes