dwyl / learn-elixir

:droplet: Learn the Elixir programming language to build functional, fast, scalable and maintainable web applications!
1.62k stars 109 forks source link

** (FunctionClauseError) no function clause matching in String.replace/4 #147

Closed nelsonic closed 4 years ago

nelsonic commented 4 years ago

I haven't changed any code in our project, just added some meta data to the mix.exs. The branch is passing Travis-CI: https://github.com/dwyl/app-mvp-phoenix/pull/24 https://travis-ci.com/dwyl/app-mvp-phoenix/builds/138754697

On localhost when I attempt to run any mix command I see the following error:

$ mix test
** (FunctionClauseError) no function clause matching in String.replace/4

    The following arguments were given to String.replace/4:

        # 1
        nil

        # 2
        "'"

        # 3
        ""

        # 4
        []

    Attempted function clauses (showing 5 out of 5):

        def replace(subject, %{__struct__: Regex} = regex, replacement, options) when is_binary(replacement) or is_function(replacement, 1)
        def replace(subject, "", "", _) when is_binary(subject)
        def replace(subject, "", replacement, options) when is_binary(subject) and is_binary(replacement)
        def replace(subject, "", replacement, options) when is_binary(subject) and is_function(replacement, 1)
        def replace(subject, pattern, replacement, options) when is_binary(subject)

    (elixir) lib/string.ex:1344: String.replace/4
    (stdlib) erl_eval.erl:680: :erl_eval.do_apply/6
    (stdlib) erl_eval.erl:888: :erl_eval.expr_list/6
    (stdlib) erl_eval.erl:411: :erl_eval.expr/5
    (stdlib) erl_eval.erl:888: :erl_eval.expr_list/6
    (stdlib) erl_eval.erl:411: :erl_eval.expr/5
    (stdlib) erl_eval.erl:888: :erl_eval.expr_list/6

The stack trace is rather unhelpful ...

Running latest Elixir/Erlang

elixir -v
Erlang/OTP 22 [erts-10.5.6] [source] [64-bit] [smp:8:8] [ds:8:8:10] [async-threads:1] [hipe] [dtrace]

Elixir 1.9.4 (compiled with Erlang/OTP 22)

🤷‍♂

nelsonic commented 4 years ago

I've tried uninstalling Elixir and re-installing it. Still get the error. Cannot see where in the code the String.replace/4 is being invoked ... 😞

nelsonic commented 4 years ago

String.replace/4 is not invoked in our codebase: image

using the following search pattern: /Users/n/code/app-mvp-phoenix/, -*/assets/*, -*/deps/* in SublimeText "find in project", found an instance in config/config.exs: image

nelsonic commented 4 years ago

I was unable to figure this out. My "solution" was the nuclear option ... 🙄

rm -rf app-mvp-phoenix
git clone git@github.com:dwyl/app-mvp-phoenix.git
cd app-mvp-phoenix
mix deps.get
mix test

....................................................................................................

Finished in 0.8 seconds
100 tests, 0 failures

Randomized with seed 460176

Works.

So frustrating! 😞

DaemonChoejur commented 3 years ago

@nelsonic Okay so I've been facing the same error on localhost.

If you are using a variable in String.replace() I suggest you use string interpolation.

Example url = 'postgres://n:n@db:5432/random?' String.replace("#{url}", "?","b")

kgautreaux commented 3 years ago

In case anyone stumbled upon this and is stumped. This can happen if you have not set your ENCRYPTION_KEYS environment variables because you didn't source your environment when you are trying to run a mix task in a new pristine shell environment. Looking at the code from above:

String.replace/4 is not invoked in our codebase: image

using the following search pattern: /Users/n/code/app-mvp-phoenix/, -*/assets/*, -*/deps/* in SublimeText "find in project", found an instance in config/config.exs: image

You can see that nil is being passed as the first argument in the pipeline because System.get_env returns nil for an absent environment variable. This is one area where the otherwise awesome Elixir pipe system obfuscates the source of the actual error.