Dialyzer missing information from several modules

I have added dialyzer to a project and it is raising lots of warnings that are clearly not a problem.

e.g.

:0:unknown_function
Function Base.encode64/1 does not exist.

The output also includes lots of information about not being able to access the necessary files.

  Recompile with +debug_info or analyze starting from source code  Could not get Core Erlang code for: /usr/local/lib/elixir/ebin/Elixir.CaseClauseError.beam
  Recompile with +debug_info or analyze starting from source code  Could not get Core Erlang code for: /usr/local/lib/elixir/ebin/Elixir.Base.beam

Recompiling as follows mix compile +debug_info makes no difference

This is something I ran to as well when upgrading from 1.7.1 -> 1.7.2, Not sure if that is directly related but it was something I ran into last night.

Did your PLT files generate?

Did you upgrade recently and do they need to be regenerated?

Do you use Dialyxer as it tends to do all this right and automatic?

Yep. I see them in _build/dev

I use Docker so it’s a new machine/container after we upgrade

Yes

Running just mix dialyzer.build I see the errors about not being able get core code.

  Recompile with +debug_info or analyze starting from source code  Could not get Core Erlang code for: /usr/local/lib/elixir/ebin/Elixir.Application.beam

That sounds so exceptionally odd, like elixir was compiled with a different erlang version…

Are you using asdf? Are you matching versions? What is the result of elixir --version from inside of the container?

Elixir version is

Erlang/OTP 21 [erts-10.0.5] [source] [64-bit] [smp:4:4] [ds:4:4:10] [async-threads:1] [hipe]

Elixir 1.7.2 (compiled with Erlang/OTP 19)

I’m not sure of exactly what steps were done to compile the erlang/elixir but I am using the standard Docker image.

FROM elixir:1.7.2-alpine

first line in Dockerfile

That seams like it could be a possible cause. I am trying to work out exactly what this issue is saying

I’ve no idea how to trigger a recompile of elixir with the updated OTP version

My output is this just as a comparison:

╰─➤  elixir --version
Erlang/OTP 21 [erts-10.0.5] [source] [64-bit] [smp:1:1] [ds:1:1:10] [async-threads:1] [hipe]

Elixir 1.7.2 (compiled with Erlang/OTP 21)

Of which I use asdf (including in a base docker container that is updated on occasion that others use as their base) to grab all the proper versions (like elixir 1.7.2-otp-21 for example to go along with the erlang 21.0.5).

I’m unsure if that’s actually the cause, but it’s worth trying, maybe there is a prebuilt container with the most updated versions of all that? Or at least matching versions?

You can unravel the chain of installation steps by reaching the Dockerfile source for those images - I echo @OvermindDL1 that it does sound like a mismatch but as long as your image pulls are fresh these should be the contents, which are compiled appropriately for Erlang 21 + Elixir 1.7.2. You could confirm with docker history [--human] elixir:1.7.2-alpine.

Mine looks like this:

Digest: sha256:279ebda267cc2ed3c3ad7fb04c93612a2008a02e75d233de8fbaa255ab24a492
Status: Image is up to date for elixir:1.7.2-alpine
IMAGE               CREATED             CREATED BY                                      SIZE                COMMENT
97d4954089b0        8 days ago          /bin/sh -c #(nop)  CMD ["iex"]                  0B
<missing>           8 days ago          /bin/sh -c set -xe  && ELIXIR_DOWNLOAD_URL="…   8.89MB
<missing>           8 days ago          /bin/sh -c #(nop)  ENV ELIXIR_VERSION=v1.7.2…   0B
<missing>           8 days ago          /bin/sh -c #(nop)  CMD ["erl"]                  0B
<missing>           8 days ago          /bin/sh -c set -xe  && OTP_DOWNLOAD_URL="htt…   67.5MB
<missing>           8 days ago          /bin/sh -c #(nop)  ENV OTP_VERSION=21.0.5       0B
<missing>           6 weeks ago         /bin/sh -c #(nop)  CMD ["/bin/sh"]              0B
<missing>           6 weeks ago         /bin/sh -c #(nop) ADD file:25f61d70254b9807a…   4.41MB

There is an alternate syntax for pull if you want to be very precise, which looks like:

docker pull elixir:1.7.2-alpine@sha256:279ebda267cc2ed3c3ad7fb04c93612a2008a02e75d233de8fbaa255ab24a492

https://hub.docker.com/_/elixir/

https://hub.docker.com/_/erlang/

I’ve generally noticed you to be a person who’s really thoughtful in how you approach things - so I’m curious what inspires you to use asdf within a Docker image, where you rarely if ever switch between multiple separate versions? I can imagine several arguments for or against.

Well I have a ‘base’ docker image where I built erlang, elixir, rust, C++ build essentials, etc… that I use for a lot of compiling. I try to keep it up to date (rust is the fastest updater!), then when I build I base ‘those’ images on this image so they have a ready-to-use build ecosystem for all that I need (I also use it as the base to run things in too though to be honest…).

Note the ‘built erlang, elixir’ part, I used to build from source so I could control everything precisely to match on how I run it, but I changed it to asdf just a little bit ago because it saves so much time when I’m updating my image. So for me it’s just an I’m Lazy and want it to go Faster thing. ^.^;

1 Like

So it looks like the problem is related to what OTP version Elixir was compiled on.

I have replace FROM elixir:1.7.2-alpine with the Dockerfile code here https://github.com/c0b/docker-elixir/blob/4d7e883e8213ea3230204e350ead05a078108b63/1.7/alpine/Dockerfile

I now no longer see the warning about Could not get Core erlang code

I have gone from ~300 errors to ~100.

However the majority of the remaining errors are still as follows.

:0:unknown_function
Function Ace.HTTP.Service.start_link/2 does not exist.
________________________________________________________________________________
:0:unknown_function
Function Ace.HTTP2.ping/2 does not exist.
________________________________________________________________________________
:0:unknown_function
Function Ace.HTTP2.send/2 does not exist.
________________________________________________________________________________
:0:unknown_function
Function Ace.HTTP2.Client.start_link/2 does not exist.
________________________________________________________________________________
:0:unknown_function
Function Ace.HTTP2.Client.stream/1 does not exist.
________________________________________________________________________________
:0:unknown_function
Function Fcmex.push/2 does not exist.
________________________________________________________________________________
:0:unknown_function
Function Mix.env/0 does not exist.

These functions clearly do exist

Dialyxer has a way to build a plt of a projects dependencies, I thought it did that by default, maybe it’s an option that has to be called?

I had just forgotten to add some applications to the list of applications. Weird that omission doesn’t seem to have effected anything else in the project

It would effect your release of it, like via distillary and such. :slight_smile:

1 Like

Erlang/OTP 21’s version of Dialyzer ended support for the OTP-19-style debug info chunk. You need to use a version of Elixir compiled with OTP 20 or higher.

2 Likes

FYI For an asdf users hitting similar issues, you need to use the Elixir version compiled with your Erlang version. See https://github.com/asdf-vm/asdf-elixir/blob/master/README.md#elixir-precompiled-versions

Eg, instead of your .tool-versions looking like

elixir 1.7.3
erlang 21.0.8

use

elixir 1.7.3-otp-21
erlang 21.0.8
5 Likes