No function clause matching in String.split/3

I have this:

  defmodule MyAppp.MyFileUploader do
    use Plug.Builder

    @cfg Application.get_env(:my_app, MyAppp.Endpoint)
    plug Plug.Static, at: @cfg[:key1], from: @cfg[:key2]
    plug Plug.Static, at: @cfg[:key3], from: {:my_app, "priv/static_assets"}, gzip: false

    def not_found(conn, _) do
      send_resp(conn, 404, "not found")
    end
  end

Exception during compilation - when running “mix phx.server”:

  == Compilation error in file lib/my_app_web/my_file_uploader.ex ==
  ** (FunctionClauseError) no function clause matching in String.split/3    
      
      The following arguments were given to String.split/3:
      
          # 1
          nil
      
          # 2
          "/"
      
          # 3
          []
      
      Attempted function clauses (showing 4 out of 4):
      
          def split(string, %Regex{} = pattern, options) when is_binary(string)
          def split(string, "", options) when is_binary(string)
          def split(string, pattern, []) when is_tuple(pattern) or is_binary(string)
          def split(string, pattern, options) when is_binary(string)
      
      (elixir) lib/string.ex:383: String.split/3
      (plug) lib/plug/router/utils.ex:116: Plug.Router.Utils.split/1
      (plug) lib/plug/static.ex:150: Plug.Static.init/1
      (plug) lib/plug/builder.ex:214: Plug.Builder.init_module_plug/4
      (plug) lib/plug/builder.ex:198: anonymous fn/5 in Plug.Builder.compile/3
      (elixir) lib/enum.ex:1899: Enum."-reduce/3-lists^foldl/2-0-"/3
      (plug) lib/plug/builder.ex:196: Plug.Builder.compile/3
      (plug) expanding macro: Plug.Builder.__before_compile__/1
      lib/my_app_web/file_uploader.ex:1: MyAppWeb.MyFileUploader (module)
      (elixir) lib/kernel/parallel_compiler.ex:198: anonymous fn/4 in Kernel.ParallelCompiler.spawn_workers/6

I can’t figure out what line cases that.

2 Likes

What is the value of @cfg?

Please insert between @cfg Application.… and plug … this: IO.inspect @cfg.

Probably you have not yet configured your Application environment when that code is hit by the compiler.

1 Like

Yes, checking:

https://github.com/elixir-plug/plug/blob/v1.6.0/lib/plug/router/utils.ex#L116

https://github.com/elixir-plug/plug/blob/v1.6.0/lib/plug/static.ex#L150

https://hexdocs.pm/elixir/Keyword.html#fetch!/2

https://github.com/elixir-plug/plug/blob/v1.6.0/lib/plug/builder.ex#L214

https://github.com/elixir-plug/plug/blob/v1.6.0/lib/plug/builder.ex#L198

https://github.com/elixir-plug/plug/blob/v1.6.0/lib/plug/builder.ex#L133

tells you that either at: @cfg[:key1] or at: @cfg[:key3] evaluates to at: nil - given that in:

def split(bin) do
  for segment <- String.split(bin, "/"), segment != "", do: segment
end

bin must have been nil to explain the error message. So in

      at: opts |> Keyword.fetch!(:at) |> Plug.Router.Utils.split()

opts (of Plug.Static.init/1) must have contained a {:at, nil} keyword.