hexpm / hex

Package manager for the Erlang ecosystem.
https://hex.pm
977 stars 187 forks source link

Conflicting declarations for path dependencies are not tracked #972

Closed axelson closed 1 year ago

axelson commented 1 year ago

When a root project has path dependencies that have a common dependency that has conflicting declarations a proper error message is not returned to the user.

Instead an error message like this is returned:

Because your app depends on phoenix_live_view empty which doesn't match any versions, version solving failed. ** (Mix) Hex dependency resolution failed

supersimple commented 1 year ago

Hi Jason, Can you diagram your dependency tree for this issue (the top-level deps and the shared transient dependency?) Do they depend on a different/conflicting version of the transient dependency?

axelson commented 1 year ago

Hi Todd! :wave: My dependency tree is slightly complicated :sweat_smile:

Here's a portion of the current dependency tree of the app in question (but note that not all the code is pushed up): 2023-01-21 2023-01-21 16 03 22 excalidraw

And here's info about the entire huge deps tree

Raw deps_tree.dot: [deps_tree.dot.zip](https://github.com/hexpm/hex/files/10473609/deps_tree.dot.zip) ![deps_tree](https://user-images.githubusercontent.com/9973/213898166-240dbab0-49b9-408d-ac82-810a27ab438e.png)

And here's the full error message:

$ mix deps.get Because your app depends on phoenix_live_view empty which doesn't match any versions, version solving failed. ** (Mix) Hex dependency resolution failed

axelson commented 1 year ago

Okay, I've created an actually useful and minimal reproduction. Here's what I believe to be the key information:

mix.exs: {:phoenix_live_view, "~> 0.17.5"} mix.exs: {:hello_phoenix, path: "extra/hello_phoenix"} mix.lock {:hex, :phoenix_live_view, "0.17.12", ... extra/hello_phoenix/mix.exs: {:phoenix_live_view, "~> 0.18.3"}

And here are the detailed reproduction steps for this (or at least a very similar issue):

git clone git@github.com:Main-Proxy/main_proxy_demo.git
cd main_proxy_demo
git checkout repro
mix local.hex 2.0.1
mix deps.get
# Prints out
Resolving Hex dependencies...
Resolution completed in 0.038s
Because your app depends on phoenix_live_view empty which doesn't match any versions, version solving failed.
** (Mix) Hex dependency resolution failed

mix local.hex 1.0.1
mix deps.get
# Prints out
Resolving Hex dependencies...

Failed to use "phoenix_live_view" (version 0.17.12) because
  extra/hello_phoenix/mix.exs requires ~> 0.18.3
  mix.lock specifies 0.17.12

** (Mix) Hex dependency resolution failed, change the version requirements of your dependencies or unlock them (by using mix deps.update or mix deps.unlock). If you are unable to resolve the conflicts you can try overriding with {:dependency, "~> 1.0", override: true}

Relevant portion of mix deps.tree (hello_phoenix is a path dep):

├── phoenix_live_view ~> 0.17.5 (Hex package)
├── hello_phoenix (extra/hello_phoenix)
│   ├── phoenix_live_view ~> 0.18.3 (Hex package)

Note: I also tried with mix archive.install github hexpm/hex and I got the same result as hex 2.0.1. With 2.0.0 I got a different error:

Resolving Hex dependencies...
#Incompatibility<#Term<your app>, cause: {:conflict, #Incompatibility<#Term<not phoenix_live_view 0.17.12 (optional)>, cause: {:conflict, #Incompatibility<#Term<the lock>, #Term<not phoenix_live_view 0.17.12 (optional)>, cause: :dependency>, #Incompatibility<#Term<your app>, #Term<not the lock>, cause: :dependency>}>, #Incompatibility<#Term<your app>, #Term<not phoenix_live_view ~> 0.18.3>, cause: :dependency>}>
Resolution completed in 0.029s
Because "the lock" specifies phoenix_live_view 0.17.12, phoenix_live_view 0.17.12 is required.
So, because your app depends on phoenix_live_view ~> 0.18.3, version solving failed.
** (Mix) Hex dependency resolution failed
ericmj commented 1 year ago

Thanks for reproducing with a minimal dependency tree @axelson. Like you say, the issue here is the poor error message, we need to show where the conflicting dependency declarations of phoenix_live_view comes from.

This probably needs be fixed in hex_solver. It currently only supports a single top-level declaration of a dependency so hex merges the two phoenix_live_view declarations before passing them to hex_solver:

mix.exs: {:phoenix_live_view, "~> 0.17.5"} extra/hello_phoenix/mix.exs: {:phoenix_live_view, "~> 0.18.3"}

becomes {:phoenix_live_view, #Constraint.Empty<>} since "~> 0.17.5" ^ "~> 0.18.3" has no overlapping versions so the intersection of the two version ranges is the empty set.

LostKobrakai commented 1 year ago

I just ran into this as well. The error message really isn't helpful. I would've liked to see what's causing the conflict instead of a general "nothing I can do here".

Nicd commented 1 year ago

José also had a minimal reproduction example (https://www.irccloud.com/pastebin/vAMBlh8i/):

Mix.install([
    {:phoenix, "~> 1.7.0"},
    {:scrivener_html, github: "jaimeiniesta/scrivener_html", branch: "relax_phoenix_dep"},
])
axelson commented 1 year ago

I'm still getting an error on my reproduction https://github.com/hexpm/hex/issues/972#issuecomment-1407134069

This is after running mix archive.install github hexpm/hex branch main which I think gets #989. However the error is different now:

$ mix deps.get
Resolving Hex dependencies...
** (KeyError) key :label not found in: nil. If you are using the dot syntax, such as map.field, make sure the left-hand side of the dot is a map
    (hex 2.0.7-dev) lib/hex/remote_converger.ex:336: anonymous fn/2 in Hex.RemoteConverger.verify_otp_app_names/2
    (elixir 1.14.3) lib/map.ex:687: Map.update/4
    (hex 2.0.7-dev) lib/hex/remote_converger.ex:335: Hex.RemoteConverger.verify_otp_app_names/2
    (hex 2.0.7-dev) lib/hex/remote_converger.ex:62: Hex.RemoteConverger.run_solver/5
    (mix 1.14.3) lib/mix/dep/converger.ex:118: Mix.Dep.Converger.all/4
    (mix 1.14.3) lib/mix/dep/converger.ex:74: Mix.Dep.Converger.converge/4
    (mix 1.14.3) lib/mix/dep/fetcher.ex:16: Mix.Dep.Fetcher.all/3
    (mix 1.14.3) lib/mix/tasks/deps.get.ex:31: Mix.Tasks.Deps.Get.run/1
ericmj commented 1 year ago

@axelson I cannot reproduce your error:

> git clone git@github.com:Main-Proxy/main_proxy_demo.git
Cloning into 'main_proxy_demo'...
remote: Enumerating objects: 231, done.
remote: Counting objects: 100% (231/231), done.
remote: Compressing objects: 100% (161/161), done.
remote: Total 231 (delta 71), reused 200 (delta 41), pack-reused 0
Receiving objects: 100% (231/231), 81.83 KiB | 517.00 KiB/s, done.
Resolving deltas: 100% (71/71), done.
> cd main_proxy_demo
> git checkout repro
branch 'repro' set up to track 'origin/repro' by rebasing.
Switched to a new branch 'repro'
> mix deps.get
* Getting exsync (https://github.com/falood/exsync.git)
remote: Enumerating objects: 364, done.
remote: Counting objects: 100% (26/26), done.
remote: Compressing objects: 100% (19/19), done.
remote: Total 364 (delta 8), reused 16 (delta 4), pack-reused 338
Resolving Hex dependencies...
Resolution completed in 0.044s
Because your app depends on hello_phoenix which depends on phoenix_live_view ~> 0.18.3, phoenix_live_view ~> 0.18.3 is required.
So, because your app depends on phoenix_live_view ~> 0.17.5, version solving failed.
** (Mix) Hex dependency resolution failed
axelson commented 1 year ago

Hmm, I can reproduce that (KeyError) key :label not found in: nil error on my desktop but not my laptop (both are running Linux Mint). The weird thing is that they're both using the same versions of elixir and erlang:

> asdf current
elixir          1.14.3-otp-25   /home/jason/.tool-versions
erlang          25.2.3          /home/jason/.tool-versions

I'm not sure what else could be different between the two environments. Is there a way to verify the specific commit of hex that I'm using?

ericmj commented 1 year ago

mix hex.info gives the version but not the commit. You can try running again mix archive.install github hexpm/hex branch main to make sure you are on the latest commit.

Also make sure you are in the same directory as your .tool-versions file as different Hex installations are used based on the Elixir version asdf is using.