# Buggy code
def json_query(data, expr):
    """Query data using jmespath query language ( http://jmespath.org ). Example:
    - debug: msg="{{ instance | json_query(tagged_instances[*].block_device_mapping.*.volume_id') }}"
    """
    if not HAS_LIB:
        raise AnsibleError(
            'You need to install "jmespath" prior to running json_query filter'
        )

    return jmespath.search(expr, data)


# Traceback (JMESPathTypeError)
TASK [Delete Application Version for current branch if more than 3 exist.] *****
task path: /builds/cloud-platform/gitlab_ci_elasticbeanstalk/.ci/deploy.yml:101
An exception occurred during task execution. The full traceback is:
Traceback (most recent call last):
File "/usr/local/lib/python2.7/site-packages/ansible/executor/task_executor.py", line 90, in run
items = self._get_loop_items()
File "/usr/local/lib/python2.7/site-packages/ansible/executor/task_executor.py", line 193, in _get_loop_items
loop_terms = listify_lookup_plugin_terms(terms=self._task.loop_args, templar=templar, loader=self._loader, fail_on_undefined=True, convert_bare=False)
File "/usr/local/lib/python2.7/site-packages/ansible/utils/listify.py", line 34, in listify_lookup_plugin_terms
terms = templar.template(terms.strip(), convert_bare=convert_bare, fail_on_undefined=fail_on_undefined)
File "/usr/local/lib/python2.7/site-packages/ansible/template/__init__.py", line 383, in template
disable_lookups=disable_lookups,
File "/usr/local/lib/python2.7/site-packages/ansible/template/__init__.py", line 583, in do_template
res = j2_concat(rf)
File "<template>", line 10, in root
File "/usr/local/lib/python2.7/site-packages/ansible/plugins/filter/json_query.py", line 40, in json_query
return jmespath.search(expr, data)
File "/usr/local/lib/python2.7/site-packages/jmespath/__init__.py", line 12, in search
return parser.Parser().parse(expression).search(data, options=options)
File "/usr/local/lib/python2.7/site-packages/jmespath/parser.py", line 524, in search
result = interpreter.visit(self.parsed, value)
File "/usr/local/lib/python2.7/site-packages/jmespath/visitor.py", line 66, in visit
return method(node, *args, **kwargs)
File "/usr/local/lib/python2.7/site-packages/jmespath/visitor.py", line 227, in visit_pipe
result = self.visit(node, result)
File "/usr/local/lib/python2.7/site-packages/jmespath/visitor.py", line 66, in visit
return method(node, *args, **kwargs)
File "/usr/local/lib/python2.7/site-packages/jmespath/visitor.py", line 227, in visit_pipe
result = self.visit(node, result)
File "/usr/local/lib/python2.7/site-packages/jmespath/visitor.py", line 66, in visit
return method(node, *args, **kwargs)
File "/usr/local/lib/python2.7/site-packages/jmespath/visitor.py", line 138, in visit_filter_projection
if self._is_true(self.visit(comparator_node, element)):
File "/usr/local/lib/python2.7/site-packages/jmespath/visitor.py", line 66, in visit
return method(node, *args, **kwargs)
File "/usr/local/lib/python2.7/site-packages/jmespath/visitor.py", line 129, in visit_function_expression
return self._functions.call_function(node['value'], resolved_args)
File "/usr/local/lib/python2.7/site-packages/jmespath/functions.py", line 89, in call_function
self._validate_arguments(resolved_args, signature, function_name)
File "/usr/local/lib/python2.7/site-packages/jmespath/functions.py", line 100, in _validate_arguments
return self._type_check(args, signature, function_name)
File "/usr/local/lib/python2.7/site-packages/jmespath/functions.py", line 107, in _type_check
function_name)
File "/usr/local/lib/python2.7/site-packages/jmespath/functions.py", line 122, in _type_check_single
self._convert_to_jmespath_type(actual_typename), types)
JMESPathTypeError: In function starts_with(), invalid type for value: new-modules-561, expected one of: ['string'], received: "unknown"
fatal: [localhost]: FAILED! => {
"failed": true,
"msg": "Unexpected failure during module execution.",
"stdout": ""
}

# Fixed code
def json_query(data, expr):
    """Query data using jmespath query language ( http://jmespath.org ). Example:
    - debug: msg="{{ instance | json_query(tagged_instances[*].block_device_mapping.*.volume_id') }}"
    """
    if not HAS_LIB:
        raise AnsibleError(
            'You need to install "jmespath" prior to running json_query filter'
        )

    try:
        return jmespath.search(expr, data)
    except jmespath.exceptions.JMESPathError as e:
        raise AnsibleFilterError("JMESPathError in json_query filter plugin:\n%s" % e)
    except Exception as e:
        # For older jmespath, we can get ValueError and TypeError without much info.
        raise AnsibleFilterError(
            "Error in jmespath.search in json_query filter plugin:\n%s" % e
        )