Making Sense of Ash install problems

Having read the book, I’m keen to explore Ash a bit more, but I’m falling at the first hurdle - the creation of a new project.

Here’s my current Erlang and Elixir:

marksmith@Marks-macbook elixir_lizards % elixir -v
Erlang/OTP 29 [erts-17.0.1] [source] [64-bit] [smp:8:8] [ds:8:8:10] [async-threads:1] [jit] [dtrace]
Elixir 1.20.0 (compiled with Erlang/OTP 29)

And here’s the minmal Ash setup I created from the get-started page:

sh <(curl 'https://ash-hq.org/install/elixir_lizards') 
    && cd elixir_lizards && mix igniter.install ash 
    --setup --yes

Here goes, below. I know open source aint an obligation, ‘yeah, help us fix it’ and all, but as a newbie to Elixir, I’m out of my depth. I am going to pull out the errors as comments and try to resolve them, or seek help as I go.

Macbook Pro M1, 16Gb, Sonoma 14.4.1,

marksmith@Marks-macbook Projects % sh <(curl 'https://ash-hq.org/install/elixir_lizards') 
&& cd elixir_lizards && mix igniter.install ash 
--setup --yes
% Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
Dload  Upload   Total   Spent    Left  Speed
100  1844  100  1844    0     0   5184      0 --:--:-- --:--:-- --:--:--  5179

Elixir is already installed ✓

Installing igniter_new archive...
Resolving Hex dependencies...
Resolution completed in 0.009s
New:
igniter_new 0.5.33

* Getting igniter_new (Hex package)
  All dependencies have been fetched
  Compiling 7 files (.ex)
  Generated igniter_new app
  Generated archive "igniter_new-0.5.33.ez" with MIX_ENV=prod
* creating /Users/marksmith/.mix/archives/igniter_new-0.5.33

Creating new Elixir project 'elixir_lizards' with the following packages:

15:11:24.413 \[notice\] TLS :client: In state :wait_cert_cr at ssl_handshake.erl:2278 generated CLIENT ALERT: Fatal - Handshake Failure

* {:bad_cert, :max_path_length_reached}


* creating README.md
* creating .formatter.exs
* creating .gitignore
* creating mix.exs
* creating lib
* creating lib/elixir_lizards.ex
* creating test
* creating test/test_helper.exs
* creating test/elixir_lizards_test.exs

Your Mix project was created successfully.
You can use "mix" to compile it, test it, and more:

cd elixir_lizards
mix test


Run "mix help" for more commands.
Fetching and compiling dependencies ⠘    warning: the variable "prefix" is accessed inside size(...) of a bitstring but it was defined outside of the match. You must precede it with the pin operator
│
50 │     with <<value::size(prefix), rest::binary>> <- bitstring do
│                        \~
│
└─ lib/hpax/types.ex:50:24: HPAX.Types.decode_integer/2

warning: the variable “length” is accessed inside size(…) of a bitstring but it was defined outside of the match. You must precede it with the pin operator


77 │          <<contents::binary-size(length), rest::binary>> <- rest do
│                                  \~
│
└─ lib/hpax/types.ex:77:34: HPAX.Types.decode_binary/1

warning: the variable “padding_size” is accessed inside size(…) of a bitstring but it was defined outside of the match. You must precede it with the pin operator


79 │     <<padding::size(padding_size)>> = padding
│                     \~
│
└─ lib/hpax/huffman.ex:79:21: HPAX.Huffman.decode/1

Fetching and compiling dependencies ⢀warning: "xref: \[exclude: ...\]" in your mix.exs file is deprecated, instead use: "elixirc_options: \[no_warn_undefined: ...\]"
(mix 1.20.0) lib/mix/tasks/compile.elixir.ex:243: Mix.Tasks.Compile.Elixir.xref_exclude_opts/2
(mix 1.20.0) lib/mix/tasks/compile.elixir.ex:142: Mix.Tasks.Compile.Elixir.run/1
(mix 1.20.0) lib/mix/task.ex:502: anonymous fn/3 in Mix.Task.run_task/5
(mix 1.20.0) lib/mix/task.compiler.ex:299: Mix.Task.Compiler.run_compiler/2
(mix 1.20.0) lib/mix/task.compiler.ex:287: Mix.Task.Compiler.run/4
(mix 1.20.0) lib/mix/tasks/compile.all.ex:75: Mix.Tasks.Compile.All.do_run/2

Fetching and compiling dependencies ⠐     warning: this clause of defp range_end_key/1 is never used (or it will always fail/warn when invoked)
│
118 │   defp range_end_key(nil), do: {0, 0}
│        \~
│
└─ lib/ex_ast/rewriter.ex:118:8: ExAST.Rewriter.range_end_key/1

warning: the following clause is redundant:

def label({:%, _, [name, _]})

it has type:

dynamic({:%, term(), non_empty_list(term())})

previous clauses have already matched on the following types:

{atom(), term(), empty_list() or non_empty_list(term(), term())}


52 │   def label({:%, \_, \[name, \_\]}), do: {:struct, alias_parts(name)}
│       \~
│
└─ lib/ex_ast/diff/normalize.ex:52:7: ExAST.Diff.Normalize.label/1

warning: the following clause is redundant:

def label({:%{}, _, kvs}) when is_list(kvs)

it has type:

dynamic({:%{}, term(), empty_list() or non_empty_list(term(), term())})

previous clauses have already matched on the following types:

{atom(), term(), empty_list() or non_empty_list(term(), term())}


54 │   def label({:%{}, \_, kvs}) when is_list(kvs),
│       \~
│
└─ lib/ex_ast/diff/normalize.ex:54:7: ExAST.Diff.Normalize.label/1

Fetching and compiling dependencies ⢘     warning: the following conditional expression will always succeed:

 is_atom(arg)

because it evaluates to:

 dynamic(true)

where “arg” was given the type:

 # type: dynamic(atom())
 # from: lib/spitfire/env.ex:218:8
 is_atom(arg)

type warning found at:


220 │       with true <- is_atom(arg) and Code.ensure_loaded?(arg),
│       \~\~\~\~\~\~\~\~\~\~\~\~\~\~\~\~\~\~\~\~\~\~\~\~\~\~\~\~\~\~\~\~\~\~\~\~\~\~\~\~\~\~\~\~\~\~\~\~\~\~\~\~\~\~\~
│
└─ lib/spitfire/env.ex:220: Spitfire.Env.expand/3

Fetching and compiling dependencies ⠈      warning: comparison between distinct types found:

  token == :eof

given types:

  dynamic(not :"," and not :eof and not nil and not :"}") == :eof

where “token” was given the types:

  # type: dynamic(not nil)
  # from: lib/spitfire.ex:1702:13
  token == nil

  # type: dynamic(not :eof and not nil)
  # from: lib/spitfire.ex:1702:29
  token == :eof

  # type: dynamic(not :"," and not :eof and not nil)
  # from: lib/spitfire.ex:1706:45
  token == :","

  # type: dynamic(not :"," and not :eof and not nil and not :"}")
  # from: lib/spitfire.ex:1706:62
  token == :"}"

While Elixir can compare across all types, you are comparing across types which are always disjoint, and the result is either always true or always false

type warning found at:


1706 │           (token_type == :assoc_op or token == :"," or token == :"}" or token == :eof) -> 
│                                                                               \~
│
└─ lib/spitfire.ex:1706:79: Spitfire.skip_call_args/2

Fetching and compiling dependencies ⡄warning: "xref: \[exclude: ...\]" in your mix.exs file is deprecated, instead use: "elixirc_options: \[no_warn_undefined: ...\]"
(mix 1.20.0) lib/mix/tasks/compile.elixir.ex:243: Mix.Tasks.Compile.Elixir.xref_exclude_opts/2
(mix 1.20.0) lib/mix/tasks/compile.elixir.ex:142: Mix.Tasks.Compile.Elixir.run/1
(mix 1.20.0) lib/mix/task.ex:502: anonymous fn/3 in Mix.Task.run_task/5
(mix 1.20.0) lib/mix/task.compiler.ex:299: Mix.Task.Compiler.run_compiler/2
(mix 1.20.0) lib/mix/task.compiler.ex:287: Mix.Task.Compiler.run/4
(mix 1.20.0) lib/mix/tasks/compile.all.ex:75: Mix.Tasks.Compile.All.do_run/2

Fetching and compiling dependencies ⢽warning: "xref: \[exclude: ...\]" in your mix.exs file is deprecated, instead use: "elixirc_options: \[no_warn_undefined: ...\]"
(mix 1.20.0) lib/mix/tasks/compile.elixir.ex:243: Mix.Tasks.Compile.Elixir.xref_exclude_opts/2
(mix 1.20.0) lib/mix/tasks/compile.elixir.ex:142: Mix.Tasks.Compile.Elixir.run/1
(mix 1.20.0) lib/mix/task.ex:502: anonymous fn/3 in Mix.Task.run_task/5
(mix 1.20.0) lib/mix/task.compiler.ex:299: Mix.Task.Compiler.run_compiler/2
(mix 1.20.0) lib/mix/task.compiler.ex:287: Mix.Task.Compiler.run/4
(mix 1.20.0) lib/mix/tasks/compile.all.ex:75: Mix.Tasks.Compile.All.do_run/2

Fetching and compiling dependencies ⣷     warning: unknown key .issues in expression:

 igniter.issues

the given type does not have the given key:

 dynamic(%Rewrite{
   sources: term(),
   extensions: term(),
   hooks: term(),
   dot_formatter: term(),
   excluded: term()
 })

where “igniter” was given the type:

 # type: dynamic(%Rewrite{})
 # from: lib/igniter/test.ex:427:24
 Rewrite.source(igniter, path)

type warning found at:


435 │       if !Enum.any?(igniter.issues, fn found_issue -> 
│                             \~\~\~\~\~\~
│
└─ lib/igniter/test.ex:435:29: Igniter.Test.assert_has_issue/3

Fetching and compiling dependencies ✔
Initializing local git repository, staging all files, and committing ✔
checking for igniter in project ✔
Updating project's igniter dependency ✔
compiling igniter ✔
setting up igniter ✔
fetching deps ✔
compiling ash ✔
`ash.install` ✔
Resolving Hex dependencies...
Resolution completed in 0.104s
Unchanged:
ash 3.29.3
crux 0.1.3
decimal 3.1.1
ecto 3.14.0
ets 0.9.0
ex_ast 0.12.0
finch 0.23.0
glob_ex 0.1.11
hpax 1.0.3
igniter 0.8.2
iterex 0.1.2
jason 1.4.5
mime 2.0.7
mint 1.9.0
multigraph 0.16.1-mg.4
nimble_options 1.1.1
nimble_pool 1.1.0
owl 0.13.1
reactor 1.0.2
req 0.6.2
rewrite 1.3.0
sourceror 1.12.2
spark 2.7.2
spitfire 0.3.13
splode 0.3.1
stream_data 1.3.0
telemetry 1.4.2
text_diff 0.1.0
yamerl 0.10.0
yaml_elixir 2.12.2
ymlr 5.1.5
All dependencies have been fetched
==> ash
warning: the following clause cannot match because the previous clauses already matched all possible values:

  _ ->

it attempts to match on the result of:

  strip_load?(initial_data)

which has the already matched type:

  dynamic(false)

type warning found at:


2769 │       if strip_load?(initial_data) do
│       \~\~\~\~\~\~\~\~\~\~\~\~\~\~\~\~\~\~\~\~\~\~\~\~\~\~\~\~\~\~\~
│
└─ lib/ash/actions/read/read.ex:2769: Ash.Actions.Read.for_read/5

warning: the following clause cannot match because the previous clauses already matched all possible values:

  _ ->

it attempts to match on the result of:

  prefer_existing_loads?(query)

which has the already matched type:

  dynamic(false)

type warning found at:


2778 │         if prefer_existing_loads?(query) do
│         \~\~\~\~\~\~\~\~\~\~\~\~\~\~\~\~\~\~\~\~\~\~\~\~\~\~\~\~\~\~\~\~\~\~\~
│
└─ lib/ash/actions/read/read.ex:2778: Ash.Actions.Read.for_read/5

could not compile dependency :ash, "mix compile" failed. Errors may have been logged above. You can recompile this dependency with "mix deps.compile ash --force", update it with "mix deps.update ash" or clean it with "mix deps.clean ash"
==> elixir_lizards
\*\* (Mix) the application :ash has a different value set for key :bulk_actions_default_to_errors? during runtime compared to compile time. Since this application environment entry was marked as compile time, this difference can lead to different behavior than expected:

* Compile time value was not set
* Runtime value was set to: true

To fix this error, you might:

* Make the runtime value match the compile time one

* Recompile your project. If the misconfigured application is a dependency, you may need to run "mix deps.clean ash --build"

* Alternatively, you can disable this check. If you are using releases, you can set :validate_compile_env to false in your release configuration. If you are using Mix to start your system, you can pass the --no-validate-compile-env flag

Task failed (exit code 1): mix ash.setup

Tasks that did not run:
• mix ash.setup

\*\* (Mix) mix ash.setup exited with code 1
marksmith@Marks-macbook elixir_lizards

Unsolved: ssl_handshake, max_path_length_reached

The first problem:

I wonder if this is even an Ash/Elixir problem, or even if it IS a problem, but there’s not a lot to go on.

A bit of digging seems to suggest there’s a certificate chain that is too long. I’m not sure what I can do about that. Is there a ‘detailed’ mode for Ash installs?

Maybe its a local thing? Here’s my mix hex.config output:

https_proxy: nil (default)
config_home: "/Users/marksmith/.hex" (default)
api_key: nil (default)
api_url: "https://hex.pm/api" (default)
cacerts_path: nil (default)
cache_home: "/Users/marksmith/.hex" (default)
ci: false (default)
data_home: "/Users/marksmith/.hex" (default)
debug_solver: false (default)
diff_command: "git diff --no-index __PATH1__ __PATH2__" (default)
http_concurrency: 8 (default)
http_proxy: nil (default)
http_timeout: nil (default)
mirror_url: nil (default)
no_proxy: nil (default)
no_short_urls: false (default)
no_verify_repo_origin: false (default)
offline: false (default)
repos_key: nil (default)
resolve_verbose: false (default)
trusted_mirror_url: nil (default)
unsafe_https: false (default)
unsafe_registry: false (default)

There was a plug error introduced and was fixed by a patch release. Try upgrading your deps and checking the current versions.

Also, there is an error that surfaces in Elixir 1.20.1 when running igniter to create a new project, so also upgrade Elixir to 1.20.2.

1 Like

Hi Frank - I’ve updated to Elixir 1.20.2 as you suggested and the project now compiles. Many thanks.

I still have the cert path problem, but I’m going to leave that for a cooler day!

Did you try running mix hex.outdated and seeing if plug is up to date/what version is installed?

Edit: I should also note, you can generally ignore warnings for your dep compilation, only the ones for your app itself are actionable unless you want to work upstream.

1 Like

Having updated to the latest elixir and erlang, the syntax errors have gone, though the cert path issue remains and there’s a dozen-ish elixir type errors to look at. Tomorrow.

mix hex.outdated
Dependency  Only      Current  Latest  Status      
ash                   3.29.3   3.29.3  Up-to-date  
igniter     dev,test  0.8.2    0.8.2   Up-to-date  
sourceror   dev,test  1.12.2   1.12.2  Up-to-date  

Just to clarify:

❯ mix hex.info plug
Compose web applications with functions

Config: {:plug, "~> 1.20"}
Locked version: 1.20.1

Plug 1.20.0 is the problematic release, so it would be good to double-check you don’t have it installed.

1 Like

This is fixed in the latest version of igniter. Issue reported here: igniter.new TLS version check fails with OTP 29 due to hardcoded `depth: 2` · Issue #386 · ash-project/igniter · GitHub

2 Likes

Many thanks @zachdaniel and @albin for the quick turnaround. I can see a merge onto main and an update to igniter to 0.5.34. Running mix archive.install hex igniter_new --force got me that version and repaving the demo app with the curl script shows the fix from 2 to 10 length fixed it.

2 Likes