<h2 dir="auto">Checklist</h2>
<h4 dir="auto">Celery report</h4>
<p dir="auto">software -&gt; celery:4.2.0rc4 (windowlicker) kombu:4.2.1 py:3.6.5<br>
billiard:3.5.0.3 py-amqp:2.3.2<br>
platform -&gt; system:Linux arch:64bit, ELF imp:CPython<br>
loader   -&gt; celery.loaders.app.AppLoader<br>
settings -&gt; transport:amqp results:redis://redis/0</p>
<p dir="auto">broker_url: 'amqp://user:********<a class="user-mention notranslate" data-hovercard-type="organization" data-hovercard-url="/orgs/rabbitmq/hovercard" data-octo-click="hovercard-link-click" data-octo-dimensions="link_type:self" href="https://github.com/rabbitmq">@rabbitmq</a>:5672/test'<br>
result_backend: 'redis://redis/0'</p>
<h2 dir="auto">Steps to reproduce</h2>
<p dir="auto">When trying to create workflows which are started within a task like this:</p>
<div class="highlight highlight-source-python notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="#app.py
@app.task
def add(x, y):
    return x + y


@app.task
def kickstart():
    test_chain = (
        add.s(1, 1) | 
        add.s(2) | 
        group(
            add.s(3),
            add.s(4)
        )
    )
    result = test_chain()
    return result"><pre class="notranslate"><span class="pl-c">#app.py</span>
<span class="pl-en">@<span class="pl-s1">app</span>.<span class="pl-s1">task</span></span>
<span class="pl-k">def</span> <span class="pl-en">add</span>(<span class="pl-s1">x</span>, <span class="pl-s1">y</span>):
    <span class="pl-k">return</span> <span class="pl-s1">x</span> <span class="pl-c1">+</span> <span class="pl-s1">y</span>


<span class="pl-en">@<span class="pl-s1">app</span>.<span class="pl-s1">task</span></span>
<span class="pl-k">def</span> <span class="pl-en">kickstart</span>():
    <span class="pl-s1">test_chain</span> <span class="pl-c1">=</span> (
        <span class="pl-s1">add</span>.<span class="pl-en">s</span>(<span class="pl-c1">1</span>, <span class="pl-c1">1</span>) <span class="pl-c1">|</span> 
        <span class="pl-s1">add</span>.<span class="pl-en">s</span>(<span class="pl-c1">2</span>) <span class="pl-c1">|</span> 
        <span class="pl-en">group</span>(
            <span class="pl-s1">add</span>.<span class="pl-en">s</span>(<span class="pl-c1">3</span>),
            <span class="pl-s1">add</span>.<span class="pl-en">s</span>(<span class="pl-c1">4</span>)
        )
    )
    <span class="pl-s1">result</span> <span class="pl-c1">=</span> <span class="pl-en">test_chain</span>()
    <span class="pl-k">return</span> <span class="pl-s1">result</span></pre></div>
<p dir="auto">one cannot build a graph out of the result of the <code class="notranslate">kickstart</code> task:</p>
<div class="highlight highlight-source-python notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="&gt;&gt;&gt; import app
&gt;&gt;&gt; res = app.kickstart.delay()
&gt;&gt;&gt; res.graph"><pre class="notranslate"><span class="pl-c1">&gt;&gt;</span><span class="pl-c1">&gt;</span> <span class="pl-k">import</span> <span class="pl-s1">app</span>
<span class="pl-c1">&gt;&gt;</span><span class="pl-c1">&gt;</span> <span class="pl-s1">res</span> <span class="pl-c1">=</span> <span class="pl-s1">app</span>.<span class="pl-s1">kickstart</span>.<span class="pl-en">delay</span>()
<span class="pl-c1">&gt;&gt;</span><span class="pl-c1">&gt;</span> <span class="pl-s1">res</span>.<span class="pl-s1">graph</span></pre></div>
<p dir="auto">A <code class="notranslate">TypeError: unhashable type: 'GroupResult'</code> is raised</p>
<h2 dir="auto">Expected behavior</h2>
<p dir="auto">A graph should be constructed.</p>
<h2 dir="auto">Actual behavior</h2>
<p dir="auto">A <code class="notranslate">TypeError: unhashable type: 'GroupResult'</code> is raised:</p>
<div class="snippet-clipboard-content notranslate position-relative overflow-auto" data-snippet-clipboard-copy-content="KeyError                                  Traceback (most recent call last)
~/.local/share/virtualenvs/project-cdmlHYK5/lib/python3.6/site-packages/kombu/utils/objects.py in __get__(self, obj, type)
     41         try:
---&gt; 42             return obj.__dict__[self.__name__]
     43         except KeyError:

KeyError: 'graph'

During handling of the above exception, another exception occurred:

TypeError                                 Traceback (most recent call last)
&lt;ipython-input-3-dd95ac617ced&gt; in &lt;module&gt;()
----&gt; 1 res.graph

~/.local/share/virtualenvs/project-cdmlHYK5/lib/python3.6/site-packages/kombu/utils/objects.py in __get__(self, obj, type)
     42             return obj.__dict__[self.__name__]
     43         except KeyError:
---&gt; 44             value = obj.__dict__[self.__name__] = self.__get(obj)
     45             return value
     46 

/src/celery/result.py in graph(self)
    387     @cached_property
    388     def graph(self):
--&gt; 389         return self.build_graph()
    390 
    391     @property

/src/celery/result.py in build_graph(self, intermediate, formatter)
    342         )
    343         for parent, node in self.iterdeps(intermediate=intermediate):
--&gt; 344             graph.add_arc(node)
    345             if parent:
    346                 graph.add_edge(parent, node)

/src/celery/utils/graph.py in add_arc(self, obj)
     54     def add_arc(self, obj):
     55         &quot;&quot;&quot;Add an object to the graph.&quot;&quot;&quot;
---&gt; 56         self.adjacent.setdefault(obj, [])
     57 
     58     def add_edge(self, A, B):

TypeError: unhashable type: 'GroupResult'```

I believe this is because the class `GroupResult` does not implements a `__hash__` method like the `AsyncResult` class: https://github.com/celery/celery/blob/master/celery/result.py#L353
We should probably implement `__hash__` and `__str__`."><pre lang="---------------------------------------------------------------------------" class="notranslate"><code class="notranslate">KeyError                                  Traceback (most recent call last)
~/.local/share/virtualenvs/project-cdmlHYK5/lib/python3.6/site-packages/kombu/utils/objects.py in __get__(self, obj, type)
     41         try:
---&gt; 42             return obj.__dict__[self.__name__]
     43         except KeyError:

KeyError: 'graph'

During handling of the above exception, another exception occurred:

TypeError                                 Traceback (most recent call last)
&lt;ipython-input-3-dd95ac617ced&gt; in &lt;module&gt;()
----&gt; 1 res.graph

~/.local/share/virtualenvs/project-cdmlHYK5/lib/python3.6/site-packages/kombu/utils/objects.py in __get__(self, obj, type)
     42             return obj.__dict__[self.__name__]
     43         except KeyError:
---&gt; 44             value = obj.__dict__[self.__name__] = self.__get(obj)
     45             return value
     46 

/src/celery/result.py in graph(self)
    387     @cached_property
    388     def graph(self):
--&gt; 389         return self.build_graph()
    390 
    391     @property

/src/celery/result.py in build_graph(self, intermediate, formatter)
    342         )
    343         for parent, node in self.iterdeps(intermediate=intermediate):
--&gt; 344             graph.add_arc(node)
    345             if parent:
    346                 graph.add_edge(parent, node)

/src/celery/utils/graph.py in add_arc(self, obj)
     54     def add_arc(self, obj):
     55         """Add an object to the graph."""
---&gt; 56         self.adjacent.setdefault(obj, [])
     57 
     58     def add_edge(self, A, B):

TypeError: unhashable type: 'GroupResult'```

I believe this is because the class `GroupResult` does not implements a `__hash__` method like the `AsyncResult` class: https://github.com/celery/celery/blob/master/celery/result.py#L353
We should probably implement `__hash__` and `__str__`.
</code></pre></div>
<p dir="auto">Version: celery==4.1.0</p>
<div class="snippet-clipboard-content notranslate position-relative overflow-auto" data-snippet-clipboard-copy-content="$ celery -A poc worker --loglevel=info
 
 -------------- celery@dudepro.local v4.1.0 (latentcall)
---- **** ----- 
--- * ***  * -- Darwin-16.7.0-x86_64-i386-64bit 2018-05-16 17:42:08
-- * - **** --- 
- ** ---------- [config]
- ** ---------- .&gt; app:         poc:0x10287fc18
- ** ---------- .&gt; transport:   redis://localhost:6379/0
- ** ---------- .&gt; results:     redis://localhost:6379/0
- *** --- * --- .&gt; concurrency: 12 (prefork)
-- ******* ---- .&gt; task events: OFF (enable -E to monitor tasks in this worker)
--- ***** ----- 
 -------------- [queues]
                .&gt; celery           exchange=celery(direct) key=celery
                

[tasks]
  . poc.add"><pre class="notranslate"><code class="notranslate">$ celery -A poc worker --loglevel=info
 
 -------------- celery@dudepro.local v4.1.0 (latentcall)
---- **** ----- 
--- * ***  * -- Darwin-16.7.0-x86_64-i386-64bit 2018-05-16 17:42:08
-- * - **** --- 
- ** ---------- [config]
- ** ---------- .&gt; app:         poc:0x10287fc18
- ** ---------- .&gt; transport:   redis://localhost:6379/0
- ** ---------- .&gt; results:     redis://localhost:6379/0
- *** --- * --- .&gt; concurrency: 12 (prefork)
-- ******* ---- .&gt; task events: OFF (enable -E to monitor tasks in this worker)
--- ***** ----- 
 -------------- [queues]
                .&gt; celery           exchange=celery(direct) key=celery
                

[tasks]
  . poc.add
</code></pre></div>
<p dir="auto">Celery worker runs fine, issue seems to be when the graph is built with <code class="notranslate">build_graph()</code>.</p>
<div class="snippet-clipboard-content notranslate position-relative overflow-auto" data-snippet-clipboard-copy-content="Traceback (most recent call last):
  File &quot;/Users/user/.pyenv/versions/3.6.1/envs/3.6.1-celery-poc/lib/python3.6/site-packages/kombu/utils/objects.py&quot;, line 42, in __get__
    return obj.__dict__[self.__name__]
KeyError: 'graph'

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File &quot;poc.py&quot;, line 33, in &lt;module&gt;
    root.graph.to_dot(fh)
  File &quot;/Users/user/.pyenv/versions/3.6.1/envs/3.6.1-celery-poc/lib/python3.6/site-packages/kombu/utils/objects.py&quot;, line 44, in __get__
    value = obj.__dict__[self.__name__] = self.__get(obj)
  File &quot;/Users/user/.pyenv/versions/3.6.1/envs/3.6.1-celery-poc/lib/python3.6/site-packages/celery/result.py&quot;, line 354, in graph
    return self.build_graph()
  File &quot;/Users/user/.pyenv/versions/3.6.1/envs/3.6.1-celery-poc/lib/python3.6/site-packages/celery/result.py&quot;, line 314, in build_graph
    graph.add_arc(node)
  File &quot;/Users/user/.pyenv/versions/3.6.1/envs/3.6.1-celery-poc/lib/python3.6/site-packages/celery/utils/graph.py&quot;, line 53, in add_arc
    self.adjacent.setdefault(obj, [])
TypeError: unhashable type: 'GroupResult'"><pre class="notranslate"><code class="notranslate">Traceback (most recent call last):
  File "/Users/user/.pyenv/versions/3.6.1/envs/3.6.1-celery-poc/lib/python3.6/site-packages/kombu/utils/objects.py", line 42, in __get__
    return obj.__dict__[self.__name__]
KeyError: 'graph'

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "poc.py", line 33, in &lt;module&gt;
    root.graph.to_dot(fh)
  File "/Users/user/.pyenv/versions/3.6.1/envs/3.6.1-celery-poc/lib/python3.6/site-packages/kombu/utils/objects.py", line 44, in __get__
    value = obj.__dict__[self.__name__] = self.__get(obj)
  File "/Users/user/.pyenv/versions/3.6.1/envs/3.6.1-celery-poc/lib/python3.6/site-packages/celery/result.py", line 354, in graph
    return self.build_graph()
  File "/Users/user/.pyenv/versions/3.6.1/envs/3.6.1-celery-poc/lib/python3.6/site-packages/celery/result.py", line 314, in build_graph
    graph.add_arc(node)
  File "/Users/user/.pyenv/versions/3.6.1/envs/3.6.1-celery-poc/lib/python3.6/site-packages/celery/utils/graph.py", line 53, in add_arc
    self.adjacent.setdefault(obj, [])
TypeError: unhashable type: 'GroupResult'
</code></pre></div>
<h2 dir="auto">Steps to reproduce</h2>
<div class="snippet-clipboard-content notranslate position-relative overflow-auto" data-snippet-clipboard-copy-content="import celery
from celery.canvas import group, chain

app = celery.Celery('poc')

app.conf.update(
	task_serializer='json',
	accept_content=['json'], 
	result_serializer='json',
	enable_utc=True,
	broker_url = 'redis://localhost:6379/0',
	result_backend = 'redis://localhost:6379/0'
)

@app.task
def add(x, y):
    return x + y

if __name__ == '__main__':

	res = chain(add.si(1,1), group(add.si(2,2), add.si(3,3), add.si(4,4)))()
	res.get()

	# Find root result of graph
	root = res.parent
	while root.parent is not None:
		root = root.parent

	with open('graph.dot', 'w') as fh:
		root.graph.to_dot(fh)"><pre class="notranslate"><code class="notranslate">import celery
from celery.canvas import group, chain

app = celery.Celery('poc')

app.conf.update(
	task_serializer='json',
	accept_content=['json'], 
	result_serializer='json',
	enable_utc=True,
	broker_url = 'redis://localhost:6379/0',
	result_backend = 'redis://localhost:6379/0'
)

@app.task
def add(x, y):
    return x + y

if __name__ == '__main__':

	res = chain(add.si(1,1), group(add.si(2,2), add.si(3,3), add.si(4,4)))()
	res.get()

	# Find root result of graph
	root = res.parent
	while root.parent is not None:
		root = root.parent

	with open('graph.dot', 'w') as fh:
		root.graph.to_dot(fh)
</code></pre></div>
<h2 dir="auto">Expected behavior</h2>
<p dir="auto">Generate the dotfile as expected by transforming each list item task id into a node entity with a corresponding arc for the graph.</p>
<h2 dir="auto">Actual behavior</h2>
<p dir="auto">Error shown above.</p>
<p dir="auto">Disclaimer: I am brand new to celery.</p>