Inspect.inspect/2 is undefined or private

Hello all,
I am facing an intermittent error on a system I’m running with iex -S mix phx.server.

Every once in a while, a web request will fail with the error above Inspect.inspect/2 is undefined or private (either in rendering, or in Ecto). Other threads seem to be happy to use Inspect instead. I’m rather puzzled :wink:

Edit: every once in a while, I seem to get a similar error on Poison.Encoder.encode/2 (this one on a different thread, so not web-related). Like, 99.9% of the times it works. What could it be?

I think you need IO.inspect/2 instead.

Honest question: why should be that? either the function is present and it always works or it is not present, and it should always break. What I don’zt hget is why it breaks sometimes.

Try to locate where Inspect.inspect is… maybe it is not always called.

1 Like

Hey there and welcome to the forums!
Is 'Inspect.inspect` one of your own modules / functions? Or were you looking for Kernel.inspect or IO.inspect instead? (these are the only ones I know of in the core lib)

1 Like

There is also Inspect.inspect/2 in Inspect protocol.

2 Likes

From the Inspect.inspect/2 docs:

Converts term into an algebra document.

This function shouldn’t be invoked directly, unless when implementing a custom inspect_fun to be given to Inspect.Opts. Everywhere else, Inspect.Algebra.to_doc/2 should be preferred as it handles structs and exceptions.

From the IO.inspect/2 docs:

I assume you meant Inspect.inspect/2

1 Like

Actually it sometimes crashes when used by Ecto… and sometimes when rendering a web view. Is there a way to assert that the function is available or force its loading?

Like:

12:42:47.065 mfa=:telemetry.execute/3 [error] Handler {Phoenix.Logger, [:phoenix, :router_dispatch, :start]} has failed and has been
 detached. Class=:error
Reason=:undef
Stacktrace=[
  {Inspect, :inspect,
   [
     LogfwdWeb.PageController,
     %Inspect.Opts{
       base: :decimal,
       binaries: :infer,
       char_lists: :infer,
       charlists: :infer,
       custom_options: [],
       inspect_fun: &Inspect.inspect/2,
       limit: 50,
       pretty: false,
       printable_limit: 4096,
       safe: true,
       structs: true,
       syntax_colors: [],
       width: 80
     }
   ], []},
  {Kernel, :inspect, 2, [file: 'lib/kernel.ex', line: 2203]},
  {Phoenix.Logger, :"-phoenix_router_dispatch_start/4-fun-0-", 4,
   [file: 'lib/phoenix/logger.ex', line: 234]},
  {Logger, :__do_log__, 4, [file: 'lib/logger.ex', line: 777]},
  {:telemetry, :"-execute/3-fun-0-", 4,
   [file: '/root/src/LogFwd/deps/telemetry/src/telemetry.erl', line: 135]},
  {:lists, :foreach, 2, [file: 'lists.erl', line: 1342]},
  {Phoenix.Router, :__call__, 2, [file: 'lib/phoenix/router.ex', line: 345]},
  {LogfwdWeb.Endpoint, :plug_builder_call, 2,
   [file: 'lib/logfwd_web/endpoint.ex', line: 1]},
  {LogfwdWeb.Endpoint, :"call (overridable 3)", 2,
   [file: 'lib/plug/debugger.ex', line: 136]},
  {LogfwdWeb.Endpoint, :call, 2, [file: 'lib/logfwd_web/endpoint.ex', line: 1]},
  {Phoenix.Endpoint.Cowboy2Handler, :init, 4,
   [file: 'lib/phoenix/endpoint/cowboy2_handler.ex', line: 65]},
  {:cowboy_handler, :execute, 2,
   [file: '/root/src/LogFwd/deps/cowboy/src/cowboy_handler.erl', line: 37]},
  {:cowboy_stream_h, :execute, 3,
   [file: '/root/src/LogFwd/deps/cowboy/src/cowboy_stream_h.erl', line: 300]},
  {:cowboy_stream_h, :request_process, 3,
   [file: '/root/src/LogFwd/deps/cowboy/src/cowboy_stream_h.erl', line: 291]},
  {:proc_lib, :init_p_do_apply, 3, [file: 'proc_lib.erl', line: 226]}
]

or

** (UndefinedFunctionError) function Inspect.inspect/2 is undefined or private
    (elixir 1.12.2) Inspect.inspect({:ok, %{.......}, %Inspect.Opts{base: :decimal, binaries: :infer, char_lists: :infer, charlists: :infer, custom_options: [], inspect_fun: &Inspect.inspect/2, limit: 50, pretty: false, printable_limit: 4096, safe: true, structs: true, syntax_colors: [], width: 80})
    (elixir 1.12.2) lib/kernel.ex:2203: Kernel.inspect/2
    (logfwd 0.3.12) lib/logfwd/tools.ex:424: Logfwd.Tools.jsonHttp/5
    (logfwd 0.3.12) lib/logfwd/tx/apis.ex:929: Logfwd.Teams.Apis.jsonCallGet/3
    (logfwd 0.3.12) lib/logfwd/tx/subs.ex:144: Logfwd.Teams.Subs.listSubscriptions/1
    (logfwd 0.3.12) lib/logfwd/tx/subs.ex:161: Logfwd.Teams.Subs.listSubscriptionsAsSubs/2
    (elixir 1.12.2) lib/enum.ex:2385: Enum."-reduce/3-lists^foldl/2-0-"/3
    (logfwd 0.3.12) lib/logfwd/tx/subsrv.ex:385: Logfwd.Teams.SubsSrv.handle_call/3
    (stdlib 3.15.1) gen_server.erl:721: :gen_server.try_handle_call/4
    (stdlib 3.15.1) gen_server.erl:750: :gen_server.handle_msg/6
    (stdlib 3.15.1) proc_lib.erl:226: :proc_lib.init_p_do_apply/3

or this coming from Ecto:

** (UndefinedFunction
Error) function Inspect.inspect/2 is undefined or private
    (elixir 1.12.2) Inspect.inspect("t_calls", %Inspect.Opts{base: :decimal, binaries: :infer, char_lists: :infer, charlists: :infer, custom_options: [], inspect_fun: &Inspect.inspect/2, limit: 50, pretty: false, printable_limit: 4096, safe: true, structs: true, syntax_colors: [], width: 80})
    (elixir 1.12.2) lib/kernel.ex:2203: Kernel.inspect/2
    (ecto_sql 3.5.4) lib/ecto/adapters/sql.ex:998: Ecto.Adapters.SQL.log_ok_source/1
    (ecto_sql 3.5.4) lib/ecto/adapters/sql.ex:982: Ecto.Adapters.SQL.log_iodata/2
    (logger 1.12.2) lib/logger.ex:777: Logger.__do_log__/4
    (ecto_sql 3.5.4) lib/ecto/adapters/sql.ex:948: Ecto.Adapters.SQL.log/4
    (db_connection 2.3.1) lib/db_connection.ex:1401: DBConnection.log/5
    (myxql 0.4.5) lib/myxql.ex:243: MyXQL.do_query/4
    (ecto_sql 3.5.4) lib/ecto/adapters/sql.ex:717: Ecto.Adapters.SQL.execute!/4
    (ecto_sql 3.5.4) lib/ecto/adapters/sql.ex:684: Ecto.Adapters.SQL.execute/5
    (ecto 3.5.6) lib/ecto/repo/queryable.ex:229: Ecto.Repo.Queryable.execute/4
    (ecto 3.5.6) lib/ecto/repo/queryable.ex:17: Ecto.Repo.Queryable.all/3
    (logfwd 0.3.12) lib/logfwd/tx/db/dbcall.ex:358: Logfwd.Teams.Db.DbCall.fetch_open_call_if_exists/2
    (logfwd 0.3.12) lib/logfwd/tx/db/dbcall.ex:162: Logfwd.Teams.Db.DbCall.new_call_notification/2
    (logfwd 0.3.12) lib/logfwd/tx/calltrackersrv.ex:154: Logfwd.Teams.CallTrackerSrv.call_received/3
    (logfwd 0.3.12) lib/logfwd_web/controllers/page_controller.ex:122: LogfwdWeb.PageController.notifyTenantOfCall/3
    (logfwd 0.3.12) lib/logfwd_web/controllers/page_controller.ex:108: anonymous fn/2 in LogfwdWeb.PageController.downloadEntries/1
    (elixir 1.12.2) lib/enum.ex:2385: Enum."-reduce/3-lists^foldl/2-0-"/3

I have an update, but I’m still puzzled (or just too much of a n00b): the errors above came from a system that was run as iex -S mix phx.server. Now, it’s a couple of days that it runs under a proper release, and I have zero of these issues appearing vs hundreds per day.

So it makes me think that it has something to do with code preloading and/or protocol consolidation (as Inspect is a protocol). This said, the system was running with an open but unused iex shell, so it did no recompiling at runtime or anything.

Anybody has any hints?

What is your project/0 configuration in your mix.exs?

Like:


  def project do
    [
      app: :logfwd,
      version: "0.3.27-211130d",
      elixir: "~> 1.7",
      elixirc_paths: elixirc_paths(Mix.env()),
      compilers: [:phoenix, :gettext] ++ Mix.compilers(),
      start_permanent: Mix.env() == :prod,
      aliases: aliases(),
      deps: deps(),
      docs: docs()
    ]
  end

?

Looks like a bug, because you say it works most of the times.

What specific Phoenix version are you using?

All i can suggest is install:

and run
mix decompile Elixir.Inspect --to expanded

and post the share somewhere the contents of Elixir.Inspect.ex

If you could share a reduced cased of your code, and if you know under what circumstances the error happens… that will be helpful.

I’ll try that…

I am running on Elixir 1.12.2 - Phoenix 1.5.7 - Erlang/OTP 24 [erts-12.0.2] [source] [64-bit] [smp:1:1] [ds:1:1:10] [async-threads:1] [jit] [x86_64-pc-linux-gnu] - I am pretty sure I saw it happen on my machine (Mac M1) once or twice.

My line of reasoning was that it could maybe break if some code was being reloaded on a different thread, but I don’t get why it could/should happen - nothing that I’m aware of would trigger a reload.

Here is what I did:

  • stopped my release
  • installed Decompile
  • mix clean
  • iex -S mix phx.server
  • mix decompile Elixir.Inspect --to expanded

In the few minutes that I run the project I got 8 errors from a number of places (mostly from Ecto), all of them function Inspect.inspect/2 is undefined or private.

defmodule Inspect do
  defp struct_impl_for(struct) do
    target = Module.concat(Inspect, struct)

    try do
      target.__impl__(:target)
    rescue
      _ in [UndefinedFunctionError] ->
        Inspect.Any.__impl__(:target)
    end
  end

  def inspect(term, arg2) do
    impl_for!(term).inspect(term, arg2)
  end

  def impl_for!(data) do
    impl_for(data)
  end

  def impl_for(%struct{}) do
    struct_impl_for(struct)
  end

  def impl_for(data) do
    try do
      Inspect.Tuple.__impl__(:target)
    rescue
      _ in [UndefinedFunctionError] ->
        Inspect.Any.__impl__(:target)
    end
  end

  def impl_for(data) do
    try do
      Inspect.Atom.__impl__(:target)
    rescue
      _ in [UndefinedFunctionError] ->
        Inspect.Any.__impl__(:target)
    end
  end

  def impl_for(data) do
    try do
      Inspect.List.__impl__(:target)
    rescue
      _ in [UndefinedFunctionError] ->
        Inspect.Any.__impl__(:target)
    end
  end

  def impl_for(data) do
    try do
      Inspect.Map.__impl__(:target)
    rescue
      _ in [UndefinedFunctionError] ->
        Inspect.Any.__impl__(:target)
    end
  end

  def impl_for(data) do
    try do
      Inspect.BitString.__impl__(:target)
    rescue
      _ in [UndefinedFunctionError] ->
        Inspect.Any.__impl__(:target)
    end
  end

  def impl_for(data) do
    try do
      Inspect.Integer.__impl__(:target)
    rescue
      _ in [UndefinedFunctionError] ->
        Inspect.Any.__impl__(:target)
    end
  end

  def impl_for(data) do
    try do
      Inspect.Float.__impl__(:target)
    rescue
      _ in [UndefinedFunctionError] ->
        Inspect.Any.__impl__(:target)
    end
  end

  def impl_for(data) do
    try do
      Inspect.Function.__impl__(:target)
    rescue
      _ in [UndefinedFunctionError] ->
        Inspect.Any.__impl__(:target)
    end
  end

  def impl_for(data) do
    try do
      Inspect.PID.__impl__(:target)
    rescue
      _ in [UndefinedFunctionError] ->
        Inspect.Any.__impl__(:target)
    end
  end

  def impl_for(data) do
    try do
      Inspect.Port.__impl__(:target)
    rescue
      _ in [UndefinedFunctionError] ->
        Inspect.Any.__impl__(:target)
    end
  end

  def impl_for(data) do
    try do
      Inspect.Reference.__impl__(:target)
    rescue
      _ in [UndefinedFunctionError] ->
        Inspect.Any.__impl__(:target)
    end
  end

  def impl_for(_) do
    Inspect.Any.__impl__(:target)
  end

  def __protocol__(:module) do
    Inspect
  end

  def __protocol__(:functions) do
    [inspect: 2]
  end

  def __protocol__(:consolidated?) do
    false
  end

  def __protocol__(:impls) do
    :not_consolidated
  end
end