Repository: conan-io/conan

Issue:
AssertionError (non-deterministic?) in graph evaluation
I have just seen the following error in our CI:
```
$ conan install -u -r artifactory --build=outdated ./packaging -s python=cpython -s python.version=3.6
Version range '^2.1' required by 'fbthrift/2018.05.21.00@igs/testing' resolved to 'gflags/2.2.0@igs/testing'
Version range '^2.1' required by 'folly/2018.05.21.00@igs/testing' resolved to 'gflags/2.2.0@igs/testing'
Version range '^0.3.5' required by 'folly/2018.05.21.00@igs/testing' resolved to 'glog/0.3.5@igs/testing'
Version range '^1.1' required by 'folly/2018.05.21.00@igs/testing' resolved to 'double-conversion/1.1.5@igs/testing'
glog/0.3.5@igs/testing requirement gflags/[^2.2]@igs/testing overriden by folly/2018.05.21.00@igs/testing to gflags/2.2.0@igs/testing 
Version range '^2.2' required by 'glog/0.3.5@igs/testing' valid for downstream requirement 'gflags/2.2.0@igs/testing'
Version range '^2.1' required by 'wangle/2018.05.21.00@igs/testing' resolved to 'gflags/2.2.0@igs/testing'
wangle/2018.05.21.00@igs/testing: WARN: Can't update, no package in remote
wangle/2018.05.21.00@igs/testing: Package is up to date
Traceback (most recent call last):
  File "/usr/local/lib/python3.6/dist-packages/conans/model/ref.py", line 70, in loads
    name, version, user, channel = tokens
ValueError: not enough values to unpack (expected 4, got 2)

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "/usr/local/lib/python3.6/dist-packages/conans/client/command.py", line 314, in install
    reference = ConanFileReference.loads(args.path_or_reference)
  File "/usr/local/lib/python3.6/dist-packages/conans/model/ref.py", line 73, in loads
    "OpenCV/1.0.6@user/stable" % text)
conans.errors.ConanException: Wrong package recipe reference ./packaging
Write something like OpenCV/1.0.6@user/stable

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "/usr/local/lib/python3.6/dist-packages/conans/client/command.py", line 1219, in run
    method(args[0][1:])
  File "/usr/local/lib/python3.6/dist-packages/conans/client/command.py", line 325, in install
    install_folder=args.install_folder)
  File "/usr/local/lib/python3.6/dist-packages/conans/client/conan_api.py", line 79, in wrapper
    return f(*args, **kwargs)
  File "/usr/local/lib/python3.6/dist-packages/conans/client/conan_api.py", line 482, in install
    no_imports=no_imports)
  File "/usr/local/lib/python3.6/dist-packages/conans/client/manager.py", line 258, in install
    profile.build_requires)
  File "/usr/local/lib/python3.6/dist-packages/conans/client/graph/graph_manager.py", line 108, in load_graph
    binaries_analyzer.evaluate_graph(graph, build_mode, update, remote_name)
  File "/usr/local/lib/python3.6/dist-packages/conans/client/graph/graph_binaries.py", line 138, in evaluate_graph
    self._evaluate_node(node, build_mode, update, evaluated_references, remote_name)
  File "/usr/local/lib/python3.6/dist-packages/conans/client/graph/graph_binaries.py", line 47, in _evaluate_node
    assert node.binary is None
AssertionError
```

Unfortunately, this error did not reproduce after retrying exactly the same build (with the same cache state), everything was OK. 
Likely relevant info about our CI setup: the entire `.conan` directory is cached between jobs, but it is only stored at the end of a successful job. So, while the `.conan` contents were quite possibly written by an older conan version, they were exactly the same for the unsuccessful and successful tries.

Environment info: Conan 1.5.1, Ubuntu 18.04 x86_64


Discussion:
I am getting the same AssertionError.

I can see it on `conan info .` and other commands. 

Here is the backtrace on my system. I can provide more details if needed. I am also running Conan 1.5.1, Ubuntu 18.04 x86_64. 

```Traceback (most recent call last):
  File "/usr/local/lib/python3.6/dist-packages/conans/client/command.py", line 1219, in run
    method(args[0][1:])
  File "/usr/local/lib/python3.6/dist-packages/conans/client/command.py", line 472, in info
    build=args.dry_build)
  File "/usr/local/lib/python3.6/dist-packages/conans/client/conan_api.py", line 79, in wrapper
    return f(*args, **kwargs)
  File "/usr/local/lib/python3.6/dist-packages/conans/client/conan_api.py", line 562, in info
    check_updates=update, build_mode=build)
  File "/usr/local/lib/python3.6/dist-packages/conans/client/manager.py", line 193, in info_get_graph
    build_mode=build_mode, remote_name=remote_name)
  File "/usr/local/lib/python3.6/dist-packages/conans/client/manager.py", line 156, in _get_deps_graph
    profile_build_requires=profile.build_requires)
  File "/usr/local/lib/python3.6/dist-packages/conans/client/graph/graph_manager.py", line 111, in load_graph
    profile_build_requires)
  File "/usr/local/lib/python3.6/dist-packages/conans/client/graph/graph_manager.py", line 88, in _recurse_build_requires
    remote_name, profile_build_requires)
  File "/usr/local/lib/python3.6/dist-packages/conans/client/graph/graph_manager.py", line 108, in load_graph
    binaries_analyzer.evaluate_graph(graph, build_mode, update, remote_name)
  File "/usr/local/lib/python3.6/dist-packages/conans/client/graph/graph_binaries.py", line 138, in evaluate_graph
    self._evaluate_node(node, build_mode, update, evaluated_references, remote_name)
  File "/usr/local/lib/python3.6/dist-packages/conans/client/graph/graph_binaries.py", line 47, in _evaluate_node
    assert node.binary is None
AssertionError

ERROR: 
insectoidsombrero@e82a07b10921:/host/SIOInstaller$ 
```
Note that I also get the error on my Ubuntu 16.04 test box. 
Thanks very much for your reports. Indeed this seems a bug, will try to fix as soon as possible and release it.
I have reviewed the code, and haven't been able to find the flaw so far. Everything seems correct, the assignment of value to the ``node.binary`` is done only after the assert, so in theory the assert seems correct.

Maybe if @zscgeek could provide more details, that would help (as @himikof error seems more random). If you don't want to share details publicly, don't hesitate to email recipes, or any necessary data to info@conan.io. Many thanks!
@memsharded  - Let me know what info would be helpful and I can try to package it up. 

It happens with a pretty complex set of dependancies so it's not easy to just package everything up, but I would be happy to run some traces or send some selected stuff over. 
@zscgeek If I add some prints to trace execution in one of my branches, would be able to run your project from my source branch to capture them? That would be very helpful.
Sure! No problem
On Fri, Jul 6, 2018 at 06:44 James <notifications@github.com> wrote:

> @zscgeek <https://github.com/zscgeek> If I add some prints to trace
> execution in one of my branches, would be able to run your project from my
> source branch to capture them? That would be very helpful.
>
> —
> You are receiving this because you were mentioned.
> Reply to this email directly, view it on GitHub
> <https://github.com/conan-io/conan/issues/3166#issuecomment-402998908>,
> or mute the thread
> <https://github.com/notifications/unsubscribe-auth/AADMX23ID2uF4RJkTBNJnd1enYyIojwLks5uDz-YgaJpZM4VBAo2>
> .
>

Great!

This is my branch: https://github.com/memsharded/conan/tree/feature/investigate_assertion_binary
Fork: https://github.com/memsharded/conan, branch ``feature/investigate_assertion_binary``

It is just a few prints, but I hope they can bring some light to this issue. Please copy or send me the whole output of running it. Many thanks @zscgeek !!
Hi @zscgeek 

Any chance of capturing that info? Conan 1.6 is getting closer, and I would like to check this before if possible. Many thanks!
Hello @memsharded I managed to create a use case causing the problem. I can't run you branch cause I don't have any python dev environment nor a properly internet connected pc (too much restrictions).
Just point the `$CONAN_USER_HOME` to where you have decompressed the archive and just run a `conan info path_to_conanfile.txt`

To be lightweight I tried to delete the `source` dir, the `build` dir : problem was still there. But when deleting the `package` dir the AssertionError disappeared.

Problem reproduced on linux x64 & windows x64.

Note : some packages may have been created by a prior version of conan (the 0.28.1 if my memory's good).

Link to the archive of the local repo : https://send.firefox.com/download/5aab8f4400/#6s2rVSghz22CkMVufdip3g
[conanfile.txt](https://github.com/conan-io/conan/files/2193509/conanfile.txt)

Many thanks @dkgs I have been able to reproduce. Will investigate it as soon as possible.

Resolving patch:
diff --git a/conans/client/graph/graph.py b/conans/client/graph/graph.py
--- a/conans/client/graph/graph.py
+++ b/conans/client/graph/graph.py
@@ -173,7 +173,7 @@ def compute_package_ids(self):
                     conanfile.package_id()
         return ordered
 
-    def full_closure(self, node):
+    def full_closure(self, node, private=False):
         # Needed to propagate correctly the cpp_info even with privates
         closure = OrderedDict()
         current = node.neighbors()
@@ -182,7 +182,8 @@ def full_closure(self, node):
             for n in current:
                 closure[n] = n
             for n in current:
-                for neigh in n.public_neighbors():
+                neighbors = n.public_neighbors() if not private else n.neighbors()
+                for neigh in neighbors:
                     if neigh not in new_current and neigh not in closure:
                         new_current.append(neigh)
             current = new_current
diff --git a/conans/client/graph/graph_binaries.py b/conans/client/graph/graph_binaries.py
--- a/conans/client/graph/graph_binaries.py
+++ b/conans/client/graph/graph_binaries.py
@@ -130,16 +130,15 @@ def _evaluate_node(self, node, build_mode, update, evaluated_references, remote_
     def evaluate_graph(self, deps_graph, build_mode, update, remote_name):
         evaluated_references = {}
         for node in deps_graph.nodes:
-            if not node.conan_ref:
+            if not node.conan_ref or node.binary:  # Only value should be SKIP
                 continue
-
             private_neighbours = node.private_neighbors()
             if private_neighbours:
                 self._evaluate_node(node, build_mode, update, evaluated_references, remote_name)
-                if node.binary != BINARY_BUILD:
+                if node.binary in (BINARY_CACHE, BINARY_DOWNLOAD, BINARY_UPDATE):
                     for neigh in private_neighbours:
                         neigh.binary = BINARY_SKIP
-                        closure = deps_graph.full_closure(neigh)
+                        closure = deps_graph.full_closure(neigh, private=True)
                         for n in closure:
                             n.binary = BINARY_SKIP
 


Test patch:
diff --git a/conans/test/integration/private_deps_test.py b/conans/test/integration/private_deps_test.py
--- a/conans/test/integration/private_deps_test.py
+++ b/conans/test/integration/private_deps_test.py
@@ -12,6 +12,24 @@
 
 class PrivateBinariesTest(unittest.TestCase):
 
+    def test_private_regression_skip(self):
+        # https://github.com/conan-io/conan/issues/3166
+        client = TestClient()
+        conanfile = """from conans import ConanFile
+class Pkg(ConanFile):
+    pass
+"""
+        client.save({"conanfile.py": conanfile})
+        client.run("create . Pkg/0.1@user/channel")
+        client.save({"conanfile.py": conanfile.replace("pass", "requires=('Pkg/0.1@user/channel', 'private'),")})
+        client.run("create . Pkg2/0.1@user/channel")
+        client.save({"conanfile.py": conanfile.replace("pass", "requires=('Pkg2/0.1@user/channel', 'private'),")})
+        client.run("create . Pkg3/0.1@user/channel")
+        client.save({"conanfile.py": conanfile.replace("pass", "requires=('Pkg3/0.1@user/channel', 'private'),")})
+        client.run("create . Pkg4/0.1@user/channel")
+        client.run("info Pkg4/0.1@user/channel")
+        self.assertEqual(3, str(client.out).count("Binary: Skip"))
+
     def test_private_skip(self):
         client = TestClient()
         conanfile = """from conans import ConanFile