# Buggy code
def call_listen(self, chunks, running):
    """
    Find all of the listen routines and call the associated mod_watch runs
    """
    listeners = []
    crefs = {}
    for chunk in chunks:
        crefs[(chunk["state"], chunk["name"])] = chunk
        crefs[(chunk["state"], chunk["__id__"])] = chunk
        if "listen" in chunk:
            listeners.append({(chunk["state"], chunk["__id__"]): chunk["listen"]})
        if "listen_in" in chunk:
            for l_in in chunk["listen_in"]:
                for key, val in six.iteritems(l_in):
                    listeners.append({(key, val): [{chunk["state"]: chunk["__id__"]}]})
    mod_watchers = []
    errors = {}
    for l_dict in listeners:
        for key, val in six.iteritems(l_dict):
            for listen_to in val:
                if not isinstance(listen_to, dict):
                    continue
                for lkey, lval in six.iteritems(listen_to):
                    if (lkey, lval) not in crefs:
                        rerror = {
                            _l_tag(lkey, lval): {
                                "comment": "Referenced state {0}: {1} does not exist".format(
                                    lkey, lval
                                ),
                                "name": "listen_{0}:{1}".format(lkey, lval),
                                "result": False,
                                "changes": {},
                            }
                        }
                        errors.update(rerror)
                        continue
                    to_tag = _gen_tag(crefs[(lkey, lval)])
                    if to_tag not in running:
                        continue
                    if running[to_tag]["changes"]:
                        if key not in crefs:
                            rerror = {
                                _l_tag(key[0], key[1]): {
                                    "comment": "Referenced state {0}: {1} does not exist".format(
                                        key[0], key[1]
                                    ),
                                    "name": "listen_{0}:{1}".format(key[0], key[1]),
                                    "result": False,
                                    "changes": {},
                                }
                            }
                            errors.update(rerror)
                            continue
                        chunk = crefs[key]
                        low = chunk.copy()
                        low["sfun"] = chunk["fun"]
                        low["fun"] = "mod_watch"
                        low["__id__"] = "listener_{0}".format(low["__id__"])
                        for req in STATE_REQUISITE_KEYWORDS:
                            if req in low:
                                low.pop(req)
                        mod_watchers.append(low)
    ret = self.call_chunks(mod_watchers)
    running.update(ret)
    for err in errors:
        errors[err]["__run_num__"] = self.__run_num
        self.__run_num += 1
    running.update(errors)
    return running


# Traceback (RuntimeError)
[DEBUG   ] Reading configuration from /etc/salt/minion
[DEBUG   ] Using cached minion ID from /etc/salt/minion_id: master.localhost
[DEBUG   ] Configuration file path: /etc/salt/minion
[WARNING ] Insecure logging configuration detected! Sensitive data may be logged.
[DEBUG   ] Reading configuration from /etc/salt/minion
[DEBUG   ] Determining pillar cache
[DEBUG   ] LazyLoaded jinja.render
[DEBUG   ] LazyLoaded yaml.render
[DEBUG   ] LazyLoaded jinja.render
[DEBUG   ] LazyLoaded yaml.render
[DEBUG   ] LazyLoaded state.apply
[DEBUG   ] LazyLoaded saltutil.is_running
[DEBUG   ] LazyLoaded grains.get
[DEBUG   ] LazyLoaded roots.envs
[DEBUG   ] Could not LazyLoad roots.init: 'roots.init' is not available.
[DEBUG   ] Updating roots fileserver cache
[INFO    ] Loading fresh modules for state activity
[DEBUG   ] LazyLoaded jinja.render
[DEBUG   ] LazyLoaded yaml.render
[DEBUG   ] Could not find file 'salt://recursion_error.sls' in saltenv 'base'
[DEBUG   ] In saltenv 'base', looking at rel_path 'recursion_error/init.sls' to resolve 'salt://recursion_error/init.sls'
[DEBUG   ] In saltenv 'base', ** considering ** path '/var/cache/salt/minion/files/base/recursion_error/init.sls' to resolve 'salt://recursion_error/init.sls'
[DEBUG   ] compile template: /var/cache/salt/minion/files/base/recursion_error/init.sls
[DEBUG   ] Jinja search path: ['/var/cache/salt/minion/files/base']
[PROFILE ] Time (in seconds) to render '/var/cache/salt/minion/files/base/recursion_error/init.sls' using 'jinja' renderer: 0.00553703308105
[DEBUG   ] Rendered data from file: /var/cache/salt/minion/files/base/recursion_error/init.sls:
item1:
cmd.run:
- name: cat /tmp/content
- unless: test -e /tmp/content

item2:
file.managed:
- name: /tmp/content
- contents: 'hi'
- prereq:
- item1

[DEBUG   ] LazyLoaded config.get
[DEBUG   ] Results of YAML rendering:
OrderedDict([('item1', OrderedDict([('cmd.run', [OrderedDict([('name', 'cat /tmp/content')]), OrderedDict([('unless', 'test -e /tmp/content')])])])), ('item2', OrderedDict([('file.managed', [OrderedDict([('name', '/tmp/content')]), OrderedDict([('contents', 'hi')]), OrderedDict([('prereq', ['item1'])])])]))])
[PROFILE ] Time (in seconds) to render '/var/cache/salt/minion/files/base/recursion_error/init.sls' using 'yaml' renderer: 0.00709915161133
[DEBUG   ] LazyLoaded cmd.run
[INFO    ] Running state [cat /tmp/content] at time 19:17:11.617011
[INFO    ] Executing state cmd.run for [cat /tmp/content]
[DEBUG   ] LazyLoaded cmd.retcode
[INFO    ] Executing command 'test -e /tmp/content' in directory '/root'
[DEBUG   ] output:
[DEBUG   ] Last command return code: 1
[INFO    ] Command "cat /tmp/content" would have been executed
[INFO    ] Completed state [cat /tmp/content] at time 19:17:11.637571 duration_in_ms=20.559
[DEBUG   ] LazyLoaded file.managed
[ERROR   ] An un-handled exception was caught by salt's global exception handler:
RuntimeError: maximum recursion depth exceeded
Traceback (most recent call last):
File "/bin/salt-call", line 11, in <module>
salt_call()
File "/usr/lib/python2.7/site-packages/salt/scripts.py", line 391, in salt_call
client.run()
File "/usr/lib/python2.7/site-packages/salt/cli/call.py", line 58, in run
caller.run()
File "/usr/lib/python2.7/site-packages/salt/cli/caller.py", line 134, in run
ret = self.call()
File "/usr/lib/python2.7/site-packages/salt/cli/caller.py", line 204, in call
ret['return'] = func(*args, **kwargs)
File "/usr/lib/python2.7/site-packages/salt/modules/state.py", line 592, in apply_
return sls(mods, **kwargs)
File "/usr/lib/python2.7/site-packages/salt/modules/state.py", line 1109, in sls
ret = st_.state.call_high(high_, orchestration_jid)
File "/usr/lib/python2.7/site-packages/salt/state.py", line 2531, in call_high
ret = self.call_chunks(chunks)
File "/usr/lib/python2.7/site-packages/salt/state.py", line 2017, in call_chunks
running = self.call_chunk(low, running, chunks)
File "/usr/lib/python2.7/site-packages/salt/state.py", line 2356, in call_chunk
running = self.call_chunk(low, running, chunks)
File "/usr/lib/python2.7/site-packages/salt/state.py", line 2356, in call_chunk
running = self.call_chunk(low, running, chunks)
File "/usr/lib/python2.7/site-packages/salt/state.py", line 2356, in call_chunk
running = self.call_chunk(low, running, chunks)
File "/usr/lib/python2.7/site-packages/salt/state.py", line 2356, in call_chunk
running = self.call_chunk(low, running, chunks)
File "/usr/lib/python2.7/site-packages/salt/state.py", line 2356, in call_chunk
running = self.call_chunk(low, running, chunks)
[...]
File "/usr/lib/python2.7/site-packages/salt/state.py", line 2356, in call_chunk
running = self.call_chunk(low, running, chunks)
File "/usr/lib/python2.7/site-packages/salt/state.py", line 2356, in call_chunk
running = self.call_chunk(low, running, chunks)
File "/usr/lib/python2.7/site-packages/salt/state.py", line 2356, in call_chunk
running = self.call_chunk(low, running, chunks)
File "/usr/lib/python2.7/site-packages/salt/state.py", line 2356, in call_chunk
running = self.call_chunk(low, running, chunks)
File "/usr/lib/python2.7/site-packages/salt/state.py", line 2356, in call_chunk
running = self.call_chunk(low, running, chunks)
File "/usr/lib/python2.7/site-packages/salt/state.py", line 2356, in call_chunk
running = self.call_chunk(low, running, chunks)
File "/usr/lib/python2.7/site-packages/salt/state.py", line 2356, in call_chunk
running = self.call_chunk(low, running, chunks)
File "/usr/lib/python2.7/site-packages/salt/state.py", line 2356, in call_chunk
running = self.call_chunk(low, running, chunks)
File "/usr/lib/python2.7/site-packages/salt/state.py", line 2356, in call_chunk
running = self.call_chunk(low, running, chunks)
File "/usr/lib/python2.7/site-packages/salt/state.py", line 2356, in call_chunk
running = self.call_chunk(low, running, chunks)
File "/usr/lib/python2.7/site-packages/salt/state.py", line 2356, in call_chunk
running = self.call_chunk(low, running, chunks)
File "/usr/lib/python2.7/site-packages/salt/state.py", line 2249, in call_chunk
low = self._mod_aggregate(low, running, chunks)
File "/usr/lib/python2.7/site-packages/salt/state.py", line 769, in _mod_aggregate
agg_opt = self.functions['config.option']('state_aggregate')
File "/usr/lib/python2.7/site-packages/salt/loader.py", line 1114, in __getitem__
func = super(LazyLoader, self).__getitem__(item)
File "/usr/lib/python2.7/site-packages/salt/utils/lazy.py", line 91, in __getitem__
if self._missing(key):
RuntimeError: maximum recursion depth exceeded

# Fixed code
def call_listen(self, chunks, running):
    """
    Find all of the listen routines and call the associated mod_watch runs
    """
    listeners = []
    crefs = {}
    for chunk in chunks:
        crefs[(chunk["state"], chunk["name"])] = chunk
        crefs[(chunk["state"], chunk["__id__"])] = chunk
        if "listen" in chunk:
            listeners.append({(chunk["state"], chunk["__id__"]): chunk["listen"]})
        if "listen_in" in chunk:
            for l_in in chunk["listen_in"]:
                for key, val in six.iteritems(l_in):
                    listeners.append({(key, val): [{chunk["state"]: chunk["__id__"]}]})
    mod_watchers = []
    errors = {}
    for l_dict in listeners:
        for key, val in six.iteritems(l_dict):
            for listen_to in val:
                if not isinstance(listen_to, dict):
                    found = False
                    for chunk in chunks:
                        if chunk["__id__"] == listen_to or chunk["name"] == listen_to:
                            listen_to = {chunk["state"]: chunk["__id__"]}
                            found = True
                    if not found:
                        continue
                for lkey, lval in six.iteritems(listen_to):
                    if (lkey, lval) not in crefs:
                        rerror = {
                            _l_tag(lkey, lval): {
                                "comment": "Referenced state {0}: {1} does not exist".format(
                                    lkey, lval
                                ),
                                "name": "listen_{0}:{1}".format(lkey, lval),
                                "result": False,
                                "changes": {},
                            }
                        }
                        errors.update(rerror)
                        continue
                    to_tag = _gen_tag(crefs[(lkey, lval)])
                    if to_tag not in running:
                        continue
                    if running[to_tag]["changes"]:
                        if key not in crefs:
                            rerror = {
                                _l_tag(key[0], key[1]): {
                                    "comment": "Referenced state {0}: {1} does not exist".format(
                                        key[0], key[1]
                                    ),
                                    "name": "listen_{0}:{1}".format(key[0], key[1]),
                                    "result": False,
                                    "changes": {},
                                }
                            }
                            errors.update(rerror)
                            continue
                        chunk = crefs[key]
                        low = chunk.copy()
                        low["sfun"] = chunk["fun"]
                        low["fun"] = "mod_watch"
                        low["__id__"] = "listener_{0}".format(low["__id__"])
                        for req in STATE_REQUISITE_KEYWORDS:
                            if req in low:
                                low.pop(req)
                        mod_watchers.append(low)
    ret = self.call_chunks(mod_watchers)
    running.update(ret)
    for err in errors:
        errors[err]["__run_num__"] = self.__run_num
        self.__run_num += 1
    running.update(errors)
    return running