Print a message for cycles in the graph when computing the target fingerprint

Review Request #4087 — Created July 17, 2016 and submitted

zundel
pants
zundel/remove-more-build-aux
3681
e63cf7c...
pants-reviews
benjyw, patricklaw, stuhood

While hand editing a BUILD file I introduced a cycle in the graph. The error was:

21:35:47 00:03   [complete]
               FAILURE
Exception caught: (<class 'pants.invalidation.cache_manager.CacheValidationError'>)

Exception message: Problem validating target project.tests.src.test.proto.proto in project/tests/src/test/proto: maximum recursion depth exceeded

The stack trace showed:

  ...
  File "pantsbuild.pants-1.1.0_pre6_square_20160707_01-py2-none-any.whl/pan
ts/build_graph/target.py", line 464, in dep_hash_iter
    dep_hash = dep.transitive_invalidation_hash(fingerprint_strategy)
  File "pantsbuild.pants-1.1.0_pre6_square_20160707_01-py2-none-any.whl/pan
ts/build_graph/target.py", line 467, in transitive_invalidation_hash
    dep_hashes = sorted(list(dep_hash_iter()))
  ...

This patch fixes it by trakcing the depth of these recursive calls and abort with an AddressLookupError so that we can see a trace. Now the error looks like:

Exception caught: (<class 'pants.invalidation.cache_manager.CacheValidationError'>)

Exception message: Problem validating target service.container.tests.src.test.proto.proto in service/container/tests/src/test/proto: Max depth of 300 exceeded.
  referenced from 3rdparty:com.google.inject.guice
  referenced from otherproject/components/cronjobs/annotations/src/main/java:lib
  referenced from otherproject/components/cronjobs/annotations/src/main/java:cron-jobs-processor
  referenced from otherproject/components/cronjobs/annotations/src/main/java:lib
  referenced from otherproject/components/cronjobs/annotations/src/main/java:cron-jobs-processor
  referenced from otherproject/components/cronjobs/annotations/src/main/java:lib
  ...

Added unit test.

CI running at https://travis-ci.org/pantsbuild/pants/builds/145436454

BE
  1. Don't we already detect cycles in the build graph? I'm surprised that doesn't trigger before this is ever reached.

    1. This is happening in build cache validation, so maybe we're hitting this condition before the other one is tested.

      annotation_processor(name='cron-jobs-processor',
        sources = [...],
        processors = [...],
        dependencies = [
          ':lib',
          'common-annotation-processors/src/main/java:lib',
        ],
      )
      
      java_library(name='lib',
        sources=rglobs('*.java'),
        resources=[],
        dependencies=[
          '3rdparty:com.google.inject.guice',
          ...
          ':cron-jobs-processor',
        ],
      )
      

      There is a warning that comes out:

      WARN] Injecting dependency from BuildFileAddress(BuildFile(service/container/components/cronjobs/annotations/src/main/java/BUILD, FileSystemProjectTree(/Users/zundel/Development/java)), cron-jobs-processor) on BuildFileAddress(BuildFile(service/container/components/cronjobs/annotations/src/main/java/BUILD, FileSystemProjectTree(/Users/zundel/Development/java)), lib), but the dependency is not in the BuildGraph.  This probably indicates a dependency cycle, but it is not an error until sort_targets is called on a subgraph containing the cycle.
      
    2. Hmm, so is there any case where this warning will be emitted but we won't get this infinite recursion?

      I'd defer to Patrick on this, as this warning is from his buildgraph code.

    3. I don't know if there is a case where this warning would not be printed. IMHO, the warning isn't as helpful as it could be:

      1) It is written in pants-developer-ese. Most of the words in the warning are impenetrable to end-users. Those users of pants aren't knowledgeable about injecting dependencies, BuildFileAddress, BuildFile, FileSystemProjectTree, BuildGraph or sort_targets().
      2) It prints way up at the beginning of the run and an exception at the end that looks like a bug in pants. I didn't even see it until after I had started investigating what the exception reported at the bottom really meant.

      I tried to to reproduce this with a small test case in the pants repo but the cycle detection always caught it.

      I did save off a branch in our repo that has the problem. This cycle is in a directory with lots of projects.

      When I run with a more constrained set of specs cycle detection catches it:

      ./pants compile service/container/components/cronjobs::
      ...
      07:17:37 00:02     [compile]
                       Zinc argument '-log-level' is not supported, and is subject to change/removal!
                       Zinc argument 'warn' is not supported, and is subject to change/removal!
      07:17:37 00:02     [zinc]
      07:17:37 00:02   [complete]
                     FAILURE
      Exception caught: (<class 'pants.build_graph.build_graph.CycleException'>)
      
      Exception message: Cycle detected:
          service/container/components/cronjobs/annotations/src/main/java:lib ->
          service/container/components/cronjobs/annotations/src/main/java:cron-jobs-processor ->
          service/container/components/cronjobs/annotations/src/main/java:lib
      

      But if I run with a wildcard further up the path the failure happens earlier in the build:

      ./pants compile service::
      ...
      07:18:21 00:01   [gen]
      07:18:21 00:01     [thrift]
      07:18:21 00:01     [protoc]
      07:18:22 00:02   [complete]
      Exception caught: (<class 'pants.invalidation.cache_manager.CacheValidationError'>)
      
      Exception message: Problem validating target service.container.tests.src.test.proto.proto in service/container/tests/src/test/proto: maximum recursion depth exceeded
      

      So, its bombing out when self.get_fingerprint_strategy() is called from simple_codegen_task.py. Here's the stack trace for the second one leading up to the infinite recursion:

      Exception caught: (<class 'pants.invalidation.cache_manager.CacheValidationError'>)
        File ".bootstrap/_pex/pex.py", line 328, in execute
          self._wrap_coverage(self._wrap_profiling, self._execute)
        File ".bootstrap/_pex/pex.py", line 260, in _wrap_coverage
          runner(*args)
        File ".bootstrap/_pex/pex.py", line 292, in _wrap_profiling
          runner(*args)
        File ".bootstrap/_pex/pex.py", line 371, in _execute
          return self.execute_entry(self._pex_info.entry_point)
        File ".bootstrap/_pex/pex.py", line 429, in execute_entry
          runner(entry_point)
        File ".bootstrap/_pex/pex.py", line 447, in execute_pkg_resources
          runner()
        File "/Users/zundel/.pex/install/pantsbuild.pants-1.1.0_pre6_square_20160707_01-py2-none-any.whl.27f343bc87a780ca9c2e64c0ccd3a2e6ceddb1a0/pantsbuild.pants-1.1.0_pre6_square_20160707_01-py2-none-any.whl/pants/bin/pants_exe.py", line 44, in main
          PantsRunner(exiter).run()
        File "/Users/zundel/.pex/install/pantsbuild.pants-1.1.0_pre6_square_20160707_01-py2-none-any.whl.27f343bc87a780ca9c2e64c0ccd3a2e6ceddb1a0/pantsbuild.pants-1.1.0_pre6_square_20160707_01-py2-none-any.whl/pants/bin/pants_runner.py", line 57, in run
          options_bootstrapper=options_bootstrapper)
        File "/Users/zundel/.pex/install/pantsbuild.pants-1.1.0_pre6_square_20160707_01-py2-none-any.whl.27f343bc87a780ca9c2e64c0ccd3a2e6ceddb1a0/pantsbuild.pants-1.1.0_pre6_square_20160707_01-py2-none-any.whl/pants/bin/pants_runner.py", line 46, in _run
          return LocalPantsRunner(exiter, args, env, options_bootstrapper=options_bootstrapper).run()
        File "/Users/zundel/.pex/install/pantsbuild.pants-1.1.0_pre6_square_20160707_01-py2-none-any.whl.27f343bc87a780ca9c2e64c0ccd3a2e6ceddb1a0/pantsbuild.pants-1.1.0_pre6_square_20160707_01-py2-none-any.whl/pants/bin/local_pants_runner.py", line 53, in run
          self._maybe_profiled(self._run)
        File "/Users/zundel/.pex/install/pantsbuild.pants-1.1.0_pre6_square_20160707_01-py2-none-any.whl.27f343bc87a780ca9c2e64c0ccd3a2e6ceddb1a0/pantsbuild.pants-1.1.0_pre6_square_20160707_01-py2-none-any.whl/pants/bin/local_pants_runner.py", line 50, in _maybe_profiled
          runner()
        File "/Users/zundel/.pex/install/pantsbuild.pants-1.1.0_pre6_square_20160707_01-py2-none-any.whl.27f343bc87a780ca9c2e64c0ccd3a2e6ceddb1a0/pantsbuild.pants-1.1.0_pre6_square_20160707_01-py2-none-any.whl/pants/bin/local_pants_runner.py", line 95, in _run
          result = goal_runner.run()
        File "/Users/zundel/.pex/install/pantsbuild.pants-1.1.0_pre6_square_20160707_01-py2-none-any.whl.27f343bc87a780ca9c2e64c0ccd3a2e6ceddb1a0/pantsbuild.pants-1.1.0_pre6_square_20160707_01-py2-none-any.whl/pants/bin/goal_runner.py", line 245, in run
          result = self._execute_engine()
        File "/Users/zundel/.pex/install/pantsbuild.pants-1.1.0_pre6_square_20160707_01-py2-none-any.whl.27f343bc87a780ca9c2e64c0ccd3a2e6ceddb1a0/pantsbuild.pants-1.1.0_pre6_square_20160707_01-py2-none-any.whl/pants/bin/goal_runner.py", line 234, in _execute_engine
          result = engine.execute(self._context, self._goals)
        File "/Users/zundel/.pex/install/pantsbuild.pants-1.1.0_pre6_square_20160707_01-py2-none-any.whl.27f343bc87a780ca9c2e64c0ccd3a2e6ceddb1a0/pantsbuild.pants-1.1.0_pre6_square_20160707_01-py2-none-any.whl/pants/engine/legacy_engine.py", line 26, in execute
          self.attempt(context, goals)
        File "/Users/zundel/.pex/install/pantsbuild.pants-1.1.0_pre6_square_20160707_01-py2-none-any.whl.27f343bc87a780ca9c2e64c0ccd3a2e6ceddb1a0/pantsbuild.pants-1.1.0_pre6_square_20160707_01-py2-none-any.whl/pants/engine/round_engine.py", line 224, in attempt
          goal_executor.attempt(explain)
        File "/Users/zundel/.pex/install/pantsbuild.pants-1.1.0_pre6_square_20160707_01-py2-none-any.whl.27f343bc87a780ca9c2e64c0ccd3a2e6ceddb1a0/pantsbuild.pants-1.1.0_pre6_square_20160707_01-py2-none-any.whl/pants/engine/round_engine.py", line 47, in attempt
          task.execute()
        File "/Users/zundel/.pex/install/pantsbuild.pants-1.1.0_pre6_square_20160707_01-py2-none-any.whl.27f343bc87a780ca9c2e64c0ccd3a2e6ceddb1a0/pantsbuild.pants-1.1.0_pre6_square_20160707_01-py2-none-any.whl/pants/backend/codegen/tasks/simple_codegen_task.py", line 177, in execute
          fingerprint_strategy=self.get_fingerprint_strategy()) as invalidation_check:
        File "/usr/local/Cellar/python/2.7.10_2/Frameworks/Python.framework/Versions/2.7/lib/python2.7/contextlib.py", line 17, in __enter__
          return self.gen.next()
        File "/Users/zundel/.pex/install/pantsbuild.pants-1.1.0_pre6_square_20160707_01-py2-none-any.whl.27f343bc87a780ca9c2e64c0ccd3a2e6ceddb1a0/pantsbuild.pants-1.1.0_pre6_square_20160707_01-py2-none-any.whl/pants/task/task.py", line 375, in invalidated
          invalidation_check = cache_manager.check(targets, topological_order=topological_order)
        File "/Users/zundel/.pex/install/pantsbuild.pants-1.1.0_pre6_square_20160707_01-py2-none-any.whl.27f343bc87a780ca9c2e64c0ccd3a2e6ceddb1a0/pantsbuild.pants-1.1.0_pre6_square_20160707_01-py2-none-any.whl/pants/invalidation/cache_manager.py", line 296, in check
          all_vts = self.wrap_targets(targets, topological_order=topological_order)
        File "/Users/zundel/.pex/install/pantsbuild.pants-1.1.0_pre6_square_20160707_01-py2-none-any.whl.27f343bc87a780ca9c2e64c0ccd3a2e6ceddb1a0/pantsbuild.pants-1.1.0_pre6_square_20160707_01-py2-none-any.whl/pants/invalidation/cache_manager.py", line 326, in wrap_targets
          return list(vt_iter())
        File "/Users/zundel/.pex/install/pantsbuild.pants-1.1.0_pre6_square_20160707_01-py2-none-any.whl.27f343bc87a780ca9c2e64c0ccd3a2e6ceddb1a0/pantsbuild.pants-1.1.0_pre6_square_20160707_01-py2-none-any.whl/pants/invalidation/cache_manager.py", line 323, in vt_iter
          target_key = self._key_for(target)
        File "/Users/zundel/.pex/install/pantsbuild.pants-1.1.0_pre6_square_20160707_01-py2-none-any.whl.27f343bc87a780ca9c2e64c0ccd3a2e6ceddb1a0/pantsbuild.pants-1.1.0_pre6_square_20160707_01-py2-none-any.whl/pants/invalidation/cache_manager.py", line 335, in _key_for
          fingerprint_strategy=self._fingerprint_strategy)
        File "/Users/zundel/.pex/install/pantsbuild.pants-1.1.0_pre6_square_20160707_01-py2-none-any.whl.27f343bc87a780ca9c2e64c0ccd3a2e6ceddb1a0/pantsbuild.pants-1.1.0_pre6_square_20160707_01-py2-none-any.whl/pants/invalidation/build_invalidator.py", line 81, in key_for_target
          target_key = target.transitive_invalidation_hash(fingerprint_strategy)
        File "/Users/zundel/.pex/install/pantsbuild.pants-1.1.0_pre6_square_20160707_01-py2-none-any.whl.27f343bc87a780ca9c2e64c0ccd3a2e6ceddb1a0/pantsbuild.pants-1.1.0_pre6_square_20160707_01-py2-none-any.whl/pants/build_graph/target.py", line 467, in transitive_invalidation_hash
          dep_hashes = sorted(list(dep_hash_iter()))
        File "/Users/zundel/.pex/install/pantsbuild.pants-1.1.0_pre6_square_20160707_01-py2-none-any.whl.27f343bc87a780ca9c2e64c0ccd3a2e6ceddb1a0/pantsbuild.pants-1.1.0_pre6_square_20160707_01-py2-none-any.whl/pants/build_graph/target.py", line 464, in dep_hash_iter
          dep_hash = dep.transitive_invalidation_hash(fingerprint_strategy)
        File "/Users/zundel/.pex/install/pantsbuild.pants-1.1.0_pre6_square_20160707_01-py2-none-any.whl.27f343bc87a780ca9c2e64c0ccd3a2e6ceddb1a0/pantsbuild.pants-1.1.0_pre6_square_20160707_01-py2-none-any.whl/pants/build_graph/target.py", line 467, in transitive_invalidation_hash
          dep_hashes = sorted(list(dep_hash_iter()))
        File "/Users/zundel/.pex/install/pantsbuild.pants-1.1.0_pre6_square_20160707_01-py2-none-any.whl.27f343bc87a780ca9c2e64c0ccd3a2e6ceddb1a0/pantsbuild.pants-1.1.0_pre6_square_20160707_01-py2-none-any.whl/pants/build_graph/target.py", line 464, in dep_hash_iter
      ... last two frames hkeep repeating from here ...
      
  2. 
      
ST
  1. If you have a good repro, I'd be interested to hear what the error looks like with: ./pants --enable-v2-engine.

    1. First attempt:

      $ PANTS_DEV=1 ./pants compile service:: --enable-v2-engine
      
      Exception caught: (<class 'pants.build_graph.address_lookup_error.AddressLookupError'>)
      
      Exception message: Build graph construction failed for DescendantAddresses(directory='service'):
        Computing LegacyTarget for DescendantAddresses(directory='service')
          Computing Addresses for DescendantAddresses(directory='service')
            Computing BuildDirs for DescendantAddresses(directory='service')
              Computing Files for DescendantAddresses(directory='service')
                Computing Paths for DescendantAddresses(directory='service')
                  Computing Paths for PathDirWildcard(canonical_stat=Dir(path=u'service'), symbolic_path='service', wildcard=u'*', remainder=u'**/BUILD*')
                    Computing Paths for PathDirWildcard(canonical_stat=Dir(path=u'service/exemplar'), symbolic_path=u'service/exemplar', wildcard=u'*', remainder=u'**/BUILD*')
                      Computing Paths for PathDirWildcard(canonical_stat=Dir(path=u'service/exemplar/target'), symbolic_path=u'service/exemplar/target', wildcard=u'*', remainder=u'**/BUILD*')
                        Computing Paths for PathDirWildcard(canonical_stat=Dir(path=u'service/exemplar/target/boxer'), symbolic_path=u'service/exemplar/target/boxer', wildcard=u'*', remainder=u'**/BUILD*')
                          Computing PathGlobs for PathDirWildcard(canonical_stat=Dir(path=u'service/exemplar/target/boxer'), symbolic_path=u'service/exemplar/target/boxer', wildcard=u'*', remainder=u'**/BUILD*')
                            Computing Dirs for Paths(dependencies=(Path(path=u'service/exemplar/target/boxer/app-manifest.yaml', stat=File(path=u'service/exemplar/target/boxer/app-manifest.yaml')), Path(path=u'service/exemplar/target/boxer/bin', stat=Dir(path=u'service/exemplar/target/boxer/bin')), Path(path=u'service/exemplar/target/boxer/env.yaml', stat=File(path=u'service/exemplar/target/boxer/env.yaml')), Path(path=u'service/exemplar/target/boxer/exemplar-common.yaml', stat=File(path=u'service/exemplar/target/boxer/exemplar-common.yaml')), Path(path=u'service/exemplar/target/boxer/exemplar-dc.yaml', stat=File(path=u'service/exemplar/target/boxer/exemplar-dc.yaml')), Path(path=u'service/exemplar/target/boxer/exemplar-development-with-samsa.yaml', stat=File(path=u'service/exemplar/target/boxer/exemplar-development-with-samsa.yaml')), Path(path=u'service/exemplar/target/boxer/exemplar-development.yaml', stat=File(path=u'service/exemplar/target/boxer/exemplar-development.yaml')), Path(path=u'service/exemplar/target/boxer/exemplar-iad1-development.yaml', stat=File(path=u'service/exemplar/target/boxer/exemplar-iad1-development.yaml')), Path(path=u'service/exemplar/target/boxer/exemplar-production.yaml', stat=File(path=u'service/exemplar/target/boxer/exemplar-production.yaml')), Path(path=u'service/exemplar/target/boxer/exemplar-sjc1b-development.yaml', stat=File(path=u'service/exemplar/target/boxer/exemplar-sjc1b-development.yaml')), Path(path=u'service/exemplar/target/boxer/exemplar-staging.yaml', stat=File(path=u'service/exemplar/target/boxer/exemplar-staging.yaml')), Path(path=u'service/exemplar/target/boxer/exemplar-test.yaml', stat=File(path=u'service/exemplar/target/boxer/exemplar-test.yaml')), Path(path=u'service/exemplar/target/boxer/exemplar.jar', stat=Link(path=u'service/exemplar/target/boxer/exemplar.jar'))))
                              Computing Dirs for Link(path=u'service/exemplar/target/boxer/exemplar.jar')
                                Computing ReadLink for Link(path=u'service/exemplar/target/boxer/exemplar.jar')
                                  Throw(exc=IOError(u'Absolute symlinks not supported in FileSystemProjectTree(/Users/zundel/Development/java): service/exemplar/target/boxer/exemplar.jar -> /Users/zundel/Development/java/dist/exemplar.jar',))
      

      I don't know why pants cares about this symlink that isn't in a directory covered by any BUILD target, but its transient so it was easy for me to remove.

      Second attempt:

      $ PANTS_DEV=1 ./pants compile service:: --enable-v2-engine
      Exception caught: (<class 'pants.build_graph.address_lookup_error.AddressLookupError'>)
      
      Exception message: Build graph construction failed for DescendantAddresses(directory='service'):
        Computing LegacyTarget for DescendantAddresses(directory='service')
          Computing LegacyTarget for service/exemplar-db/src/test/java:lib
            Computing LegacyTarget for service/container/components/cronjobs/annotations/src/main/java:lib
              Computing LegacyTarget for service/container/components/cronjobs/annotations/src/main/java:cron-jobs-processor
                Throw(exc=ValueError(u"No source of explicit dependency SelectNode(subject=service/container/components/cronjobs/annotations/src/main/java:lib, product=<class 'pants.engine.legacy.graph.LegacyTarget'>, variants=None, variant_key=None)",))
              Computing LegacyTarget for service/container/components/cronjobs/annotations/src/main/java:cron-jobs-processor
                Noop(msg=u"Edge would cause a cycle: TaskNode(subject=service/container/components/cronjobs/annotations/src/main/java:cron-jobs-processor, product=<class 'pants.engine.legacy.graph.LegacyTarget'>, variants=None, func=reify_legacy_graph, clause=(Subject(product=<class 'pants.engine.legacy.structs.TargetAdaptor'>, optional=False), Dependencies(product=<class 'pants.engine.legacy.graph.LegacyTarget'>, deps_product=<class 'pants.engine.legacy.structs.TargetAdaptor'>, field=u'dependencies'), Dependencies(product=<class 'pants.engine.legacy.graph.HydratedField'>, deps_product=<class 'pants.engine.legacy.structs.TargetAdaptor'>, field=u'field_adaptors')) -> TaskNode(subject=service/container/components/cronjobs/annotations/src/main/java:lib, product=<class 'pants.engine.legacy.graph.LegacyTarget'>, variants=None, func=reify_legacy_graph, clause=(Subject(product=<class 'pants.engine.legacy.structs.TargetAdaptor'>, optional=False), Dependencies(product=<class 'pants.engine.legacy.graph.LegacyTarget'>, deps_product=<class 'pants.engine.legacy.structs.TargetAdaptor'>, field=u'dependencies'), Dependencies(product=<class 'pants.engine.legacy.graph.HydratedField'>, deps_product=<class 'pants.engine.legacy.structs.TargetAdaptor'>, field=u'field_adaptors')).")
            Computing LegacyTarget for service/container/components/cronjobs/src/main/java:lib
              Throw(exc=ValueError(u"No source of explicit dependency SelectNode(subject=service/container/components/cronjobs/annotations/src/main/java:lib, product=<class 'pants.engine.legacy.graph.LegacyTarget'>, variants=None, variant_key=None)",))
            Computing LegacyTarget for service/exemplar-db/src/main/java:lib
              Computing LegacyTarget for feeds/jooq-feeds/src/main/java:lib
                Computing LegacyTarget for feeds/src/main/java:lib
                  Throw(exc=ValueError(u"No source of explicit dependency SelectNode(subject=service/container/components/cronjobs/annotations/src/main/java:lib, product=<class 'pants.engine.legacy.graph.LegacyTarget'>, variants=None, variant_key=None)",))
              Computing LegacyTarget for service/exemplar/src/main/java:lib
                Throw(exc=ValueError(u"No source of explicit dependency SelectNode(subject=service/container/components/cronjobs/annotations/src/main/java:lib, product=<class 'pants.engine.legacy.graph.LegacyTarget'>, variants=None, variant_key=None)",))
              Computing LegacyTarget for service/exemplar-db/src/main/proto:proto
                Throw(exc=ValueError(u"No source of explicit dependency SelectNode(subject=service/container/components/cronjobs/annotations/src/main/java:lib, product=<class 'pants.engine.legacy.graph.LegacyTarget'>, variants=None, variant_key=None)",))
            Computing LegacyTarget for service/container/testing/src/main/java:lib
              Throw(exc=ValueError(u"No source of explicit dependency SelectNode(subject=service/container/components/cronjobs/annotations/src/main/java:lib, product=<class 'pants.engine.legacy.graph.LegacyTarget'>, variants=None, variant_key=None)",))
          Computing LegacyTarget for service/container/testing:testing
            Computing LegacyTarget for service/container/testing:lib
              Throw(exc=ValueError(u"No source of explicit dependency SelectNode(subject=service/container/components/cronjobs/annotations/src/main/java:lib, product=<class 'pants.engine.legacy.graph.LegacyTarget'>, variants=None, variant_key=None)",))
          Computing LegacyTarget for service/exemplar:test
            Computing LegacyTarget for service/exemplar/src/test/java:test
              Computing LegacyTarget for service/exemplar/src/test/java:lib
                Throw(exc=ValueError(u"No source of explicit dependency SelectNode(subject=service/container/components/cronjobs/annotations/src/main/java:lib, product=<class 'pants.engine.legacy.graph.LegacyTarget'>, variants=None, variant_key=None)",))
          Computing LegacyTarget for service/container/components/chaos-injection/src/test/java:integration-tests
            Computing LegacyTarget for service/container/components/chaos-injection/src/test/java:lib
              Throw(exc=ValueError(u"No source of explicit dependency SelectNode(subject=service/container/components/cronjobs/annotations/src/main/java:lib, product=<class 'pants.engine.legacy.graph.LegacyTarget'>, variants=None, variant_key=None)",))
          Computing LegacyTarget for service/exemplar:shaded-jar
            Computing LegacyTarget for service/exemplar:lib
              Throw(exc=ValueError(u"No source of explicit dependency SelectNode(subject=service/container/components/cronjobs/annotations/src/main/java:lib, product=<class 'pants.engine.legacy.graph.LegacyTarget'>, variants=None, variant_key=None)",))
          Computing LegacyTarget for service/container/annotation-processors-tests/src/test/java:test
            Computing LegacyTarget for service/container/annotation-processors-tests/src/test/java:lib
              Computing LegacyTarget for jobs/pipeline/src/main/java:lib
                Computing LegacyTarget for database-sharding/src/main/java:lib
                  Throw(exc=ValueError(u"No source of explicit dependency SelectNode(subject=service/container/components/cronjobs/annotations/src/main/java:lib, product=<class 'pants.engine.legacy.graph.LegacyTarget'>, variants=None, variant_key=None)",))
              Computing LegacyTarget for jobqueue/src/main/java:lib
                Throw(exc=ValueError(u"No source of explicit dependency SelectNode(subject=service/container/components/cronjobs/annotations/src/main/java:lib, product=<class 'pants.engine.legacy.graph.LegacyTarget'>, variants=None, variant_key=None)",))
          Computing LegacyTarget for service/exemplar-db:proto
            Throw(exc=ValueError(u"No source of explicit dependency SelectNode(subject=service/container/components/cronjobs/annotations/src/main/java:lib, product=<class 'pants.engine.legacy.graph.LegacyTarget'>, variants=None, variant_key=None)",))
          Computing LegacyTarget for service/container/components/cronjobs:lib
            Throw(exc=ValueError(u"No source of explicit dependency SelectNode(subject=service/container/components/cronjobs/annotations/src/main/java:lib, product=<class 'pants.engine.legacy.graph.LegacyTarget'>, variants=None, variant_key=None)",))
          Computing LegacyTarget for service/container/components/chaos-injection/src/test/java:test
            Throw(exc=ValueError(u"No source of explicit dependency SelectNode(subject=service/container/components/cronjobs/annotations/src/main/java:lib, product=<class 'pants.engine.legacy.graph.LegacyTarget'>, variants=None, variant_key=None)",))
          Computing LegacyTarget for service/exemplar-db:shaded-jar
            Computing LegacyTarget for service/exemplar-db:lib
              Throw(exc=ValueError(u"No source of explicit dependency SelectNode(subject=service/container/components/cronjobs/annotations/src/main/java:lib, product=<class 'pants.engine.legacy.graph.LegacyTarget'>, variants=None, variant_key=None)",))
          Computing LegacyTarget for service/container/wire-tests/src/test/java:test
            Computing LegacyTarget for service/container/wire-tests/src/test/java:lib
              Computing LegacyTarget for service/container/wire-tests/src/test/proto:proto
                Throw(exc=ValueError(u"No source of explicit dependency SelectNode(subject=service/container/components/cronjobs/annotations/src/main/java:lib, product=<class 'pants.engine.legacy.graph.LegacyTarget'>, variants=None, variant_key=None)",))
          Computing LegacyTarget for service/container/components/chaos-injection:test
            Throw(exc=ValueError(u"No source of explicit dependency SelectNode(subject=service/container/components/cronjobs/annotations/src/main/java:lib, product=<class 'pants.engine.legacy.graph.LegacyTarget'>, variants=None, variant_key=None)",))
          Computing LegacyTarget for service/container/wire-tests:wire-tests
            Computing LegacyTarget for service/container/wire-tests:lib
              Throw(exc=ValueError(u"No source of explicit dependency SelectNode(subject=service/container/components/cronjobs/annotations/src/main/java:lib, product=<class 'pants.engine.legacy.graph.LegacyTarget'>, variants=None, variant_key=None)",))
          Computing LegacyTarget for service/container/wire-tests/src/test/java:integration-tests
            Throw(exc=ValueError(u"No source of explicit dependency SelectNode(subject=service/container/components/cronjobs/annotations/src/main/java:lib, product=<class 'pants.engine.legacy.graph.LegacyTarget'>, variants=None, variant_key=None)",))
          Computing LegacyTarget for service/container/annotation-processors-tests:annotation-processors-tests
            Computing LegacyTarget for service/container/annotation-processors-tests:lib
              Throw(exc=ValueError(u"No source of explicit dependency SelectNode(subject=service/container/components/cronjobs/annotations/src/main/java:lib, product=<class 'pants.engine.legacy.graph.LegacyTarget'>, variants=None, variant_key=None)",))
          Computing LegacyTarget for service/container/tests:test
            Computing LegacyTarget for service/container/tests/src/test/java:test
              Computing LegacyTarget for service/container/tests/src/test/java:lib
                Computing LegacyTarget for service/container/tests/src/test/proto:proto
                  Throw(exc=ValueError(u"No source of explicit dependency SelectNode(subject=service/container/components/cronjobs/annotations/src/main/java:lib, product=<class 'pants.engine.legacy.graph.LegacyTarget'>, variants=None, variant_key=None)",))
          Computing LegacyTarget for service/exemplar/src/test/java:integration-tests
            Throw(exc=ValueError(u"No source of explicit dependency SelectNode(subject=service/container/components/cronjobs/annotations/src/main/java:lib, product=<class 'pants.engine.legacy.graph.LegacyTarget'>, variants=None, variant_key=None)",))
          Computing LegacyTarget for service/container/testing/src/test/java:lib
            Throw(exc=ValueError(u"No source of explicit dependency SelectNode(subject=service/container/components/cronjobs/annotations/src/main/java:lib, product=<class 'pants.engine.legacy.graph.LegacyTarget'>, variants=None, variant_key=None)",))
          Computing LegacyTarget for service/container/wire-tests:test
            Throw(exc=ValueError(u"No source of explicit dependency SelectNode(subject=service/container/components/cronjobs/annotations/src/main/java:lib, product=<class 'pants.engine.legacy.graph.LegacyTarget'>, variants=None, variant_key=None)",))
          Computing LegacyTarget for service/container/components/cronjobs:test
            Computing LegacyTarget for service/container/components/cronjobs/src/test/java:test
              Computing LegacyTarget for service/container/components/cronjobs/src/test/java:lib
                Throw(exc=ValueError(u"No source of explicit dependency SelectNode(subject=service/container/components/cronjobs/annotations/src/main/java:lib, product=<class 'pants.engine.legacy.graph.LegacyTarget'>, variants=None, variant_key=None)",))
          Computing LegacyTarget for service/exemplar:hoist-artifact
            Throw(exc=ValueError(u"No source of explicit dependency SelectNode(subject=service/container/components/cronjobs/annotations/src/main/java:lib, product=<class 'pants.engine.legacy.graph.LegacyTarget'>, variants=None, variant_key=None)",))
          Computing LegacyTarget for service/container/testing/src/test/java:integration-tests
            Throw(exc=ValueError(u"No source of explicit dependency SelectNode(subject=service/container/components/cronjobs/annotations/src/main/java:lib, product=<class 'pants.engine.legacy.graph.LegacyTarget'>, variants=None, variant_key=None)",))
          Computing LegacyTarget for service/container/testing/src/test/java:test
            Throw(exc=ValueError(u"No source of explicit dependency SelectNode(subject=service/container/components/cronjobs/annotations/src/main/java:lib, product=<class 'pants.engine.legacy.graph.LegacyTarget'>, variants=None, variant_key=None)",))
          Computing LegacyTarget for service/container/components/cronjobs/annotations:annotations
            Computing LegacyTarget for service/container/components/cronjobs/annotations:lib
              Throw(exc=ValueError(u"No source of explicit dependency SelectNode(subject=service/container/components/cronjobs/annotations/src/main/java:lib, product=<class 'pants.engine.legacy.graph.LegacyTarget'>, variants=None, variant_key=None)",))
          Computing LegacyTarget for service/exemplar-db/src/test/java:test
            Throw(exc=ValueError(u"No source of explicit dependency SelectNode(subject=service/container/components/cronjobs/annotations/src/main/java:lib, product=<class 'pants.engine.legacy.graph.LegacyTarget'>, variants=None, variant_key=None)",))
          Computing LegacyTarget for service/container/annotation-processors-tests/src/test/java:integration-tests
            Throw(exc=ValueError(u"No source of explicit dependency SelectNode(subject=service/container/components/cronjobs/annotations/src/main/java:lib, product=<class 'pants.engine.legacy.graph.LegacyTarget'>, variants=None, variant_key=None)",))
          Computing LegacyTarget for service/container/testing:test
            Throw(exc=ValueError(u"No source of explicit dependency SelectNode(subject=service/container/components/cronjobs/annotations/src/main/java:lib, product=<class 'pants.engine.legacy.graph.LegacyTarget'>, variants=None, variant_key=None)",))
          Computing LegacyTarget for service/container/annotation-processors-tests:test
            Throw(exc=ValueError(u"No source of explicit dependency SelectNode(subject=service/container/components/cronjobs/annotations/src/main/java:lib, product=<class 'pants.engine.legacy.graph.LegacyTarget'>, variants=None, variant_key=None)",))
          Computing LegacyTarget for service/exemplar-db/src/test/java:integration-tests
            Throw(exc=ValueError(u"No source of explicit dependency SelectNode(subject=service/container/components/cronjobs/annotations/src/main/java:lib, product=<class 'pants.engine.legacy.graph.LegacyTarget'>, variants=None, variant_key=None)",))
          Computing LegacyTarget for service/container/tests:tests
            Computing LegacyTarget for service/container/tests:lib
              Throw(exc=ValueError(u"No source of explicit dependency SelectNode(subject=service/container/components/cronjobs/annotations/src/main/java:lib, product=<class 'pants.engine.legacy.graph.LegacyTarget'>, variants=None, variant_key=None)",))
          Computing LegacyTarget for service/container/tests/src/test/java:integration-tests
            Throw(exc=ValueError(u"No source of explicit dependency SelectNode(subject=service/container/components/cronjobs/annotations/src/main/java:lib, product=<class 'pants.engine.legacy.graph.LegacyTarget'>, variants=None, variant_key=None)",))
          Computing LegacyTarget for service/container/components/cronjobs/annotations:test
            Throw(exc=ValueError(u"No source of explicit dependency SelectNode(subject=service/container/components/cronjobs/annotations/src/main/java:lib, product=<class 'pants.engine.legacy.graph.LegacyTarget'>, variants=None, variant_key=None)",))
          Computing LegacyTarget for service/exemplar-db:exemplar-db
            Throw(exc=ValueError(u"No source of explicit dependency SelectNode(subject=service/container/components/cronjobs/annotations/src/main/java:lib, product=<class 'pants.engine.legacy.graph.LegacyTarget'>, variants=None, variant_key=None)",))
          Computing LegacyTarget for service/container/components/cronjobs:cronjobs
            Throw(exc=ValueError(u"No source of explicit dependency SelectNode(subject=service/container/components/cronjobs/annotations/src/main/java:lib, product=<class 'pants.engine.legacy.graph.LegacyTarget'>, variants=None, variant_key=None)",))
          Computing LegacyTarget for service/exemplar-db:test
            Throw(exc=ValueError(u"No source of explicit dependency SelectNode(subject=service/container/components/cronjobs/annotations/src/main/java:lib, product=<class 'pants.engine.legacy.graph.LegacyTarget'>, variants=None, variant_key=None)",))
          Computing LegacyTarget for service/container/components/cronjobs/src/test/java:integration-tests
            Throw(exc=ValueError(u"No source of explicit dependency SelectNode(subject=service/container/components/cronjobs/annotations/src/main/java:lib, product=<class 'pants.engine.legacy.graph.LegacyTarget'>, variants=None, variant_key=None)",))
          Computing LegacyTarget for service/exemplar:exemplar
            Throw(exc=ValueError(u"No source of explicit dependency SelectNode(subject=service/container/components/cronjobs/annotations/src/main/java:lib, product=<class 'pants.engine.legacy.graph.LegacyTarget'>, variants=None, variant_key=None)",))
          Computing LegacyTarget for service/exemplar-db:hoist-artifact
            Throw(exc=ValueError(u"No source of explicit dependency SelectNode(subject=service/container/components/cronjobs/annotations/src/main/java:lib, product=<class 'pants.engine.legacy.graph.LegacyTarget'>, variants=None, variant_key=None)",))
      
    2. Yea, absolute symlinks are currently banned; whether we just treat these as broken symlinks going forward will be up for debate soon.

      You got the Noop(msg=u"Edge would cause a cycle...") cycle error, but it looks it's buried under a bit too much context. If you were to attempt to build only the cyclic target the output would be a bit more usable.

      Interesting: thanks!

    3. Opened https://github.com/pantsbuild/pants/issues/3695

  2. src/python/pants/build_graph/target.py (Diff revision 1)
     
     
     
     
     
     
     
     

    I might be missing something, but will this cause this message to be logged 300 times?

    Does the except need to check the depth before logging?

    1. Yes, it does eventually print 300 times, but this line doesn't actually print anything. it just propagates the exception. The printing happens through our regular printing that handles AddresLookupErrors. We could put something in there to limit the number of exceptions it prints.

  3. 
      
BE
  1. This looks fine as far as it goes, but I would like to use this opportunity to understand how it's possible to get here without hitting cycle detection, and why that warning from the buildgraph code is a warning and not an error.

  2. 
      
ZU
  1. I tried to to reproduce this with a small test case in the pants repo but the cycle detection always caught it.

    I did save off a branch in our repo that has the problem. This cycle is in a directory with lots of projects.

    When I run with a more constrained set of specs cycle detection catches it:

    ./pants compile service/container/components/cronjobs::
    ...
    07:17:37 00:02     [compile]
                     Zinc argument '-log-level' is not supported, and is subject to change/removal!
                     Zinc argument 'warn' is not supported, and is subject to change/removal!
    07:17:37 00:02     [zinc]
    07:17:37 00:02   [complete]
                   FAILURE
    Exception caught: (<class 'pants.build_graph.build_graph.CycleException'>)
    
    Exception message: Cycle detected:
        service/container/components/cronjobs/annotations/src/main/java:lib ->
        service/container/components/cronjobs/annotations/src/main/java:cron-jobs-processor ->
        service/container/components/cronjobs/annotations/src/main/java:lib
    

    But if I run with a wildcard further up the path the failure happens earlier in the build:

    ./pants compile service::
    ...
    07:18:21 00:01   [gen]
    07:18:21 00:01     [thrift]
    07:18:21 00:01     [protoc]
    07:18:22 00:02   [complete]
    Exception caught: (<class 'pants.invalidation.cache_manager.CacheValidationError'>)
    
    Exception message: Problem validating target service.container.tests.src.test.proto.proto in service/container/tests/src/test/proto: maximum recursion depth exceeded
    

    So, its bombing out when self.get_fingerprint_strategy() is called from simple_codegen_task.py. Here's the stack trace for the second one leading up to the infinite recursion:

    Exception caught: (<class 'pants.invalidation.cache_manager.CacheValidationError'>)
      File ".bootstrap/_pex/pex.py", line 328, in execute
        self._wrap_coverage(self._wrap_profiling, self._execute)
      File ".bootstrap/_pex/pex.py", line 260, in _wrap_coverage
        runner(*args)
      File ".bootstrap/_pex/pex.py", line 292, in _wrap_profiling
        runner(*args)
      File ".bootstrap/_pex/pex.py", line 371, in _execute
        return self.execute_entry(self._pex_info.entry_point)
      File ".bootstrap/_pex/pex.py", line 429, in execute_entry
        runner(entry_point)
      File ".bootstrap/_pex/pex.py", line 447, in execute_pkg_resources
        runner()
      File "/Users/zundel/.pex/install/pantsbuild.pants-1.1.0_pre6_square_20160707_01-py2-none-any.whl.27f343bc87a780ca9c2e64c0ccd3a2e6ceddb1a0/pantsbuild.pants-1.1.0_pre6_square_20160707_01-py2-none-any.whl/pants/bin/pants_exe.py", line 44, in main
        PantsRunner(exiter).run()
      File "/Users/zundel/.pex/install/pantsbuild.pants-1.1.0_pre6_square_20160707_01-py2-none-any.whl.27f343bc87a780ca9c2e64c0ccd3a2e6ceddb1a0/pantsbuild.pants-1.1.0_pre6_square_20160707_01-py2-none-any.whl/pants/bin/pants_runner.py", line 57, in run
        options_bootstrapper=options_bootstrapper)
      File "/Users/zundel/.pex/install/pantsbuild.pants-1.1.0_pre6_square_20160707_01-py2-none-any.whl.27f343bc87a780ca9c2e64c0ccd3a2e6ceddb1a0/pantsbuild.pants-1.1.0_pre6_square_20160707_01-py2-none-any.whl/pants/bin/pants_runner.py", line 46, in _run
        return LocalPantsRunner(exiter, args, env, options_bootstrapper=options_bootstrapper).run()
      File "/Users/zundel/.pex/install/pantsbuild.pants-1.1.0_pre6_square_20160707_01-py2-none-any.whl.27f343bc87a780ca9c2e64c0ccd3a2e6ceddb1a0/pantsbuild.pants-1.1.0_pre6_square_20160707_01-py2-none-any.whl/pants/bin/local_pants_runner.py", line 53, in run
        self._maybe_profiled(self._run)
      File "/Users/zundel/.pex/install/pantsbuild.pants-1.1.0_pre6_square_20160707_01-py2-none-any.whl.27f343bc87a780ca9c2e64c0ccd3a2e6ceddb1a0/pantsbuild.pants-1.1.0_pre6_square_20160707_01-py2-none-any.whl/pants/bin/local_pants_runner.py", line 50, in _maybe_profiled
        runner()
      File "/Users/zundel/.pex/install/pantsbuild.pants-1.1.0_pre6_square_20160707_01-py2-none-any.whl.27f343bc87a780ca9c2e64c0ccd3a2e6ceddb1a0/pantsbuild.pants-1.1.0_pre6_square_20160707_01-py2-none-any.whl/pants/bin/local_pants_runner.py", line 95, in _run
        result = goal_runner.run()
      File "/Users/zundel/.pex/install/pantsbuild.pants-1.1.0_pre6_square_20160707_01-py2-none-any.whl.27f343bc87a780ca9c2e64c0ccd3a2e6ceddb1a0/pantsbuild.pants-1.1.0_pre6_square_20160707_01-py2-none-any.whl/pants/bin/goal_runner.py", line 245, in run
        result = self._execute_engine()
      File "/Users/zundel/.pex/install/pantsbuild.pants-1.1.0_pre6_square_20160707_01-py2-none-any.whl.27f343bc87a780ca9c2e64c0ccd3a2e6ceddb1a0/pantsbuild.pants-1.1.0_pre6_square_20160707_01-py2-none-any.whl/pants/bin/goal_runner.py", line 234, in _execute_engine
        result = engine.execute(self._context, self._goals)
      File "/Users/zundel/.pex/install/pantsbuild.pants-1.1.0_pre6_square_20160707_01-py2-none-any.whl.27f343bc87a780ca9c2e64c0ccd3a2e6ceddb1a0/pantsbuild.pants-1.1.0_pre6_square_20160707_01-py2-none-any.whl/pants/engine/legacy_engine.py", line 26, in execute
        self.attempt(context, goals)
      File "/Users/zundel/.pex/install/pantsbuild.pants-1.1.0_pre6_square_20160707_01-py2-none-any.whl.27f343bc87a780ca9c2e64c0ccd3a2e6ceddb1a0/pantsbuild.pants-1.1.0_pre6_square_20160707_01-py2-none-any.whl/pants/engine/round_engine.py", line 224, in attempt
        goal_executor.attempt(explain)
      File "/Users/zundel/.pex/install/pantsbuild.pants-1.1.0_pre6_square_20160707_01-py2-none-any.whl.27f343bc87a780ca9c2e64c0ccd3a2e6ceddb1a0/pantsbuild.pants-1.1.0_pre6_square_20160707_01-py2-none-any.whl/pants/engine/round_engine.py", line 47, in attempt
        task.execute()
      File "/Users/zundel/.pex/install/pantsbuild.pants-1.1.0_pre6_square_20160707_01-py2-none-any.whl.27f343bc87a780ca9c2e64c0ccd3a2e6ceddb1a0/pantsbuild.pants-1.1.0_pre6_square_20160707_01-py2-none-any.whl/pants/backend/codegen/tasks/simple_codegen_task.py", line 177, in execute
        fingerprint_strategy=self.get_fingerprint_strategy()) as invalidation_check:
      File "/usr/local/Cellar/python/2.7.10_2/Frameworks/Python.framework/Versions/2.7/lib/python2.7/contextlib.py", line 17, in __enter__
        return self.gen.next()
      File "/Users/zundel/.pex/install/pantsbuild.pants-1.1.0_pre6_square_20160707_01-py2-none-any.whl.27f343bc87a780ca9c2e64c0ccd3a2e6ceddb1a0/pantsbuild.pants-1.1.0_pre6_square_20160707_01-py2-none-any.whl/pants/task/task.py", line 375, in invalidated
        invalidation_check = cache_manager.check(targets, topological_order=topological_order)
      File "/Users/zundel/.pex/install/pantsbuild.pants-1.1.0_pre6_square_20160707_01-py2-none-any.whl.27f343bc87a780ca9c2e64c0ccd3a2e6ceddb1a0/pantsbuild.pants-1.1.0_pre6_square_20160707_01-py2-none-any.whl/pants/invalidation/cache_manager.py", line 296, in check
        all_vts = self.wrap_targets(targets, topological_order=topological_order)
      File "/Users/zundel/.pex/install/pantsbuild.pants-1.1.0_pre6_square_20160707_01-py2-none-any.whl.27f343bc87a780ca9c2e64c0ccd3a2e6ceddb1a0/pantsbuild.pants-1.1.0_pre6_square_20160707_01-py2-none-any.whl/pants/invalidation/cache_manager.py", line 326, in wrap_targets
        return list(vt_iter())
      File "/Users/zundel/.pex/install/pantsbuild.pants-1.1.0_pre6_square_20160707_01-py2-none-any.whl.27f343bc87a780ca9c2e64c0ccd3a2e6ceddb1a0/pantsbuild.pants-1.1.0_pre6_square_20160707_01-py2-none-any.whl/pants/invalidation/cache_manager.py", line 323, in vt_iter
        target_key = self._key_for(target)
      File "/Users/zundel/.pex/install/pantsbuild.pants-1.1.0_pre6_square_20160707_01-py2-none-any.whl.27f343bc87a780ca9c2e64c0ccd3a2e6ceddb1a0/pantsbuild.pants-1.1.0_pre6_square_20160707_01-py2-none-any.whl/pants/invalidation/cache_manager.py", line 335, in _key_for
        fingerprint_strategy=self._fingerprint_strategy)
      File "/Users/zundel/.pex/install/pantsbuild.pants-1.1.0_pre6_square_20160707_01-py2-none-any.whl.27f343bc87a780ca9c2e64c0ccd3a2e6ceddb1a0/pantsbuild.pants-1.1.0_pre6_square_20160707_01-py2-none-any.whl/pants/invalidation/build_invalidator.py", line 81, in key_for_target
        target_key = target.transitive_invalidation_hash(fingerprint_strategy)
      File "/Users/zundel/.pex/install/pantsbuild.pants-1.1.0_pre6_square_20160707_01-py2-none-any.whl.27f343bc87a780ca9c2e64c0ccd3a2e6ceddb1a0/pantsbuild.pants-1.1.0_pre6_square_20160707_01-py2-none-any.whl/pants/build_graph/target.py", line 467, in transitive_invalidation_hash
        dep_hashes = sorted(list(dep_hash_iter()))
      File "/Users/zundel/.pex/install/pantsbuild.pants-1.1.0_pre6_square_20160707_01-py2-none-any.whl.27f343bc87a780ca9c2e64c0ccd3a2e6ceddb1a0/pantsbuild.pants-1.1.0_pre6_square_20160707_01-py2-none-any.whl/pants/build_graph/target.py", line 464, in dep_hash_iter
        dep_hash = dep.transitive_invalidation_hash(fingerprint_strategy)
      File "/Users/zundel/.pex/install/pantsbuild.pants-1.1.0_pre6_square_20160707_01-py2-none-any.whl.27f343bc87a780ca9c2e64c0ccd3a2e6ceddb1a0/pantsbuild.pants-1.1.0_pre6_square_20160707_01-py2-none-any.whl/pants/build_graph/target.py", line 467, in transitive_invalidation_hash
        dep_hashes = sorted(list(dep_hash_iter()))
      File "/Users/zundel/.pex/install/pantsbuild.pants-1.1.0_pre6_square_20160707_01-py2-none-any.whl.27f343bc87a780ca9c2e64c0ccd3a2e6ceddb1a0/pantsbuild.pants-1.1.0_pre6_square_20160707_01-py2-none-any.whl/pants/build_graph/target.py", line 464, in dep_hash_iter
    ... last two frames hkeep repeating from here ...
    
  2. 
      
ZU
Review request changed

Status: Closed (submitted)

Change Summary:

Commit a2fe1dc

Loading...