# Buggy code
def _add_group(self, host, result_item):
    """
    Helper function to add a group (if it does not exist), and to assign the
    specified host to that group.
    """

    changed = False

    # the host here is from the executor side, which means it was a
    # serialized/cloned copy and we'll need to look up the proper
    # host object from the master inventory
    real_host = self._inventory.hosts[host.name]
    group_name = result_item.get("add_group")
    parent_group_names = result_item.get("parent_groups", [])

    for name in [group_name] + parent_group_names:
        if name not in self._inventory.groups:
            # create the new group and add it to inventory
            self._inventory.add_group(name)
            changed = True
    group = self._inventory.groups[group_name]
    for parent_group_name in parent_group_names:
        parent_group = self._inventory.groups[parent_group_name]
        parent_group.add_child_group(group)

    if real_host.name not in group.get_hosts():
        group.add_host(real_host)
        changed = True

    if group_name not in host.get_groups():
        real_host.add_group(group)
        changed = True

    if changed:
        self._inventory.reconcile_inventory()

    return changed


# Traceback (KeyError)
PLAYBOOK: rex.yml ******************************************************************************************************
1 plays in rex.yml

PLAY [localhost] *******************************************************************************************************

TASK [Gathering Facts] *************************************************************************************************
Using module file /usr/local/lib/python3.5/dist-packages/ansible/modules/system/setup.py
<127.0.0.1> ESTABLISH LOCAL CONNECTION FOR USER: root
<127.0.0.1> EXEC /bin/sh -c 'echo ~ &amp;&amp; sleep 0'
<127.0.0.1> EXEC /bin/sh -c '( umask 77 &amp;&amp; mkdir -p "` echo /root/.ansible/tmp/ansible-tmp-1508876288.0254786-168044730198300 `" &amp;&amp; echo ansible-tmp-1508876288.0254786-168044730198300="` echo /root/.ansible/tmp/ansible-tmp-1508876288.0254786-168044730198300 `" ) &amp;&amp; sleep 0'
<127.0.0.1> PUT /tmp/tmpd750uvbw TO /root/.ansible/tmp/ansible-tmp-1508876288.0254786-168044730198300/setup.py
<127.0.0.1> EXEC /bin/sh -c 'chmod u+x /root/.ansible/tmp/ansible-tmp-1508876288.0254786-168044730198300/ /root/.ansible/tmp/ansible-tmp-1508876288.0254786-168044730198300/setup.py &amp;&amp; sleep 0'
<127.0.0.1> EXEC /bin/sh -c '/usr/bin/python3 /root/.ansible/tmp/ansible-tmp-1508876288.0254786-168044730198300/setup.py; rm -rf "/root/.ansible/tmp/ansible-tmp-1508876288.0254786-168044730198300/" > /dev/null 2>&amp;1 &amp;&amp; sleep 0'
ok: [localhost]

TASK [group_by] ********************************************************************************************************
task path: /opt/app/rex.yml:18
ERROR! Unexpected Exception, this is probably a bug: 'localhost'
the full traceback was:

Traceback (most recent call last):
File "/usr/local/bin/ansible-playbook", line 106, in <module>
exit_code = cli.run()
File "/usr/local/lib/python3.5/dist-packages/ansible/cli/playbook.py", line 130, in run
results = pbex.run()
File "/usr/local/lib/python3.5/dist-packages/ansible/executor/playbook_executor.py", line 154, in run
result = self._tqm.run(play=play)
File "/usr/local/lib/python3.5/dist-packages/ansible/executor/task_queue_manager.py", line 302, in run
play_return = strategy.run(iterator, play_context)
File "/usr/local/lib/python3.5/dist-packages/ansible/plugins/strategy/linear.py", line 292, in run
results += self._wait_on_pending_results(iterator)
File "/usr/local/lib/python3.5/dist-packages/ansible/plugins/strategy/__init__.py", line 586, in _wait_on_pending_results
results = self._process_pending_results(iterator)
File "/usr/local/lib/python3.5/dist-packages/ansible/plugins/strategy/__init__.py", line 497, in _process_pending_results
self._add_group(original_host, result_item)
File "/usr/local/lib/python3.5/dist-packages/ansible/plugins/strategy/__init__.py", line 632, in _add_group
real_host = self._inventory.hosts[host.name]
KeyError: 'localhost'

# Fixed code
def _add_group(self, host, result_item):
    """
    Helper function to add a group (if it does not exist), and to assign the
    specified host to that group.
    """

    changed = False

    # the host here is from the executor side, which means it was a
    # serialized/cloned copy and we'll need to look up the proper
    # host object from the master inventory
    real_host = self._inventory.hosts.get(host.name)
    if real_host is None:
        if host.name == self._inventory.localhost.name:
            real_host = self._inventory.localhost
        else:
            raise AnsibleError("%s cannot be matched in inventory" % host.name)
    group_name = result_item.get("add_group")
    parent_group_names = result_item.get("parent_groups", [])

    for name in [group_name] + parent_group_names:
        if name not in self._inventory.groups:
            # create the new group and add it to inventory
            self._inventory.add_group(name)
            changed = True
    group = self._inventory.groups[group_name]
    for parent_group_name in parent_group_names:
        parent_group = self._inventory.groups[parent_group_name]
        parent_group.add_child_group(group)

    if real_host.name not in group.get_hosts():
        group.add_host(real_host)
        changed = True

    if group_name not in host.get_groups():
        real_host.add_group(group)
        changed = True

    if changed:
        self._inventory.reconcile_inventory()

    return changed