add inventory query options
diff --git a/reclass/core.py b/reclass/core.py
index 8082d80..6dc3254 100644
--- a/reclass/core.py
+++ b/reclass/core.py
@@ -17,7 +17,7 @@
 from reclass.settings import Settings
 from reclass.output.yaml_outputter import ExplicitDumper
 from reclass.datatypes import Entity, Classes, Parameters, Exports
-from reclass.errors import MappingFormatError, ClassNotFound, ResolveError
+from reclass.errors import MappingFormatError, ClassNotFound, ResolveError, InvQueryError, InterpolationError
 
 class Core(object):
 
@@ -101,7 +101,7 @@
                     class_entity = self._storage.get_class(klass, environment, self._settings)
                 except ClassNotFound, e:
                     e.set_nodename(nodename)
-                    raise e
+                    raise
 
                 descent = self._recurse_entity(class_entity, seen=seen,
                                                nodename=nodename, environment=environment)
@@ -123,20 +123,43 @@
         else:
             return Parameters({}, self._settings, '')
 
-    def _get_inventory(self):
+    def _get_inventory(self, all_envs, environment, queries):
         inventory = {}
         for nodename in self._storage.enumerate_nodes():
-            node = self._node_entity(nodename)
             try:
-                node.interpolate_exports()
-            except ResolveError as e:
-               e.export = nodename
-               raise e
-            inventory[nodename] = node.exports.as_dict()
+                node_base = self._storage.get_node(nodename, self._settings)
+                if node_base.environment == None:
+                    node_base.environment = self._settings.default_environment
+            except yaml.scanner.ScannerError as e:
+                if self._settings.inventory_ignore_failed_node:
+                    continue
+                else:
+                    raise
+
+            if all_envs or node_base.environment == environment:
+                node = self._node_entity(nodename)
+                if queries is None:
+                    try:
+                        node.interpolate_exports()
+                    except ResolveError as e:
+                        e.nodename = nodename
+                else:
+                    node.initialise_interpolation()
+                    for p, q in queries:
+                        try:
+                            node.interpolate_single_export(q)
+                        except ResolveError as e:
+                            e.nodename = nodename
+                            raise InvQueryError(q.contents(), e, context=p, uri=q.uri())
+                inventory[nodename] = node.exports.as_dict()
         return inventory
 
     def _node_entity(self, nodename):
-        node_entity = self._storage.get_node(nodename, self._settings)
+        try:
+            node_entity = self._storage.get_node(nodename, self._settings)
+        except InterpolationError as e:
+            e.nodename = nodename
+            raise
         if node_entity.environment == None:
             node_entity.environment = self._settings.default_environment
         base_entity = Entity(self._settings, name='base')
@@ -153,8 +176,16 @@
         ret = self._node_entity(nodename)
         ret.initialise_interpolation()
         if ret.parameters.has_inv_query() and inventory is None:
-            inventory = self._get_inventory()
-        ret.interpolate(nodename, inventory)
+            try:
+                inventory = self._get_inventory(ret.parameters.needs_all_envs(), ret.environment, ret.parameters.get_inv_queries())
+            except InvQueryError as e:
+                e.nodename = nodename
+                raise e
+        try:
+            ret.interpolate(nodename, inventory)
+        except ResolveError as e:
+            e.nodename = nodename
+            raise
         return ret
 
     def _nodeinfo_as_dict(self, nodename, entity):
@@ -173,7 +204,7 @@
     def inventory(self):
         query_nodes = set()
         entities = {}
-        inventory = self._get_inventory()
+        inventory = self._get_inventory(True, '', None)
         for n in self._storage.enumerate_nodes():
             entities[n] = self._nodeinfo(n, inventory)
             if entities[n].parameters.has_inv_query():
diff --git a/reclass/datatypes/entity.py b/reclass/datatypes/entity.py
index 5b54cf7..e88e2fa 100644
--- a/reclass/datatypes/entity.py
+++ b/reclass/datatypes/entity.py
@@ -96,6 +96,9 @@
         self.initialise_interpolation()
         self._exports.interpolate_from_external(self._parameters)
 
+    def interpolate_single_export(self, references):
+        self._exports.interpolate_single_from_external(self._parameters, references)
+
     def __eq__(self, other):
         return isinstance(other, type(self)) \
                 and self._applications == other._applications \
diff --git a/reclass/datatypes/exports.py b/reclass/datatypes/exports.py
index f8f38a1..ae5b30b 100644
--- a/reclass/datatypes/exports.py
+++ b/reclass/datatypes/exports.py
@@ -3,6 +3,9 @@
 #
 # This file is part of reclass (http://github.com/madduck/reclass)
 #
+
+import copy
+
 from parameters import Parameters
 from reclass.errors import ResolveError
 from reclass.values.value import Value
@@ -25,8 +28,6 @@
         self.merge(overdict)
 
     def interpolate_from_external(self, external):
-        self._initialise_interpolate()
-        external._initialise_interpolate()
         while len(self._unrendered) > 0:
             path, v = self._unrendered.iteritems().next()
             value = path.get_value(self._base)
@@ -41,12 +42,38 @@
                 path.set_value(self._base, new)
                 del self._unrendered[path]
 
+    def interpolate_single_from_external(self, external, query):
+        paths = {}
+        for r in query.get_inv_references():
+            paths[r] = True
+        while len(paths) > 0:
+            path, v = paths.iteritems().next()
+            if path.exists_in(self._base) and path in self._unrendered:
+                value = path.get_value(self._base)
+                if not isinstance(value, (Value, ValueList)):
+                    del paths[path]
+                    del self._unrendered[path]
+                else:
+                    try:
+                        external._interpolate_references(path, value, None)
+                        new = self._interpolate_render_from_external(external._base, path, value)
+                        path.set_value(self._base, new)
+                    except ResolveError as e:
+                        if query.ignore_failed_render():
+                            path.delete(self._base)
+                        else:
+                            raise
+                    del paths[path]
+                    del self._unrendered[path]
+            else:
+                del paths[path]
+
     def _interpolate_render_from_external(self, context, path, value):
         try:
             new = value.render(context, None)
         except ResolveError as e:
             e.context = path
-            raise e
+            raise
         if isinstance(new, dict):
             self._render_simple_dict(new, path)
         elif isinstance(new, list):
diff --git a/reclass/datatypes/parameters.py b/reclass/datatypes/parameters.py
index b55f01a..4152d11 100644
--- a/reclass/datatypes/parameters.py
+++ b/reclass/datatypes/parameters.py
@@ -14,7 +14,7 @@
 from reclass.utils.dictpath import DictPath
 from reclass.values.value import Value
 from reclass.values.valuelist import ValueList
-from reclass.errors import InfiniteRecursionError, ResolveError, InterpolationError
+from reclass.errors import InfiniteRecursionError, ResolveError, InterpolationError, ParseError, BadReferencesError
 
 class Parameters(object):
     '''
@@ -46,7 +46,8 @@
         self._uri = uri
         self._unrendered = None
         self._escapes_handled = {}
-        self._has_inv_query = False
+        self._inv_queries = []
+        self._needs_all_envs = False
         self._keep_overrides = False
         if mapping is not None:
             # we initialise by merging
@@ -71,28 +72,39 @@
         return not self.__eq__(other)
 
     def has_inv_query(self):
-        return self._has_inv_query
+        return len(self._inv_queries) > 0
+
+    def get_inv_queries(self):
+        return self._inv_queries
+
+    def needs_all_envs(self):
+        return self._needs_all_envs
 
     def as_dict(self):
         return self._base.copy()
 
-    def _wrap_value(self, value):
+    def _wrap_value(self, value, path):
         if isinstance(value, dict):
-            return self._wrap_dict(value)
+            return self._wrap_dict(value, path)
         elif isinstance(value, list):
-            return self._wrap_list(value)
+            return self._wrap_list(value, path)
         elif isinstance(value, (Value, ValueList)):
             return value
         else:
-            return Value(value, self._settings, self._uri)
+            try:
+                return Value(value, self._settings, self._uri)
+            except InterpolationError as e:
+                e.context = str(path)
+                raise
 
-    def _wrap_list(self, source):
-        return [ self._wrap_value(v) for v in source ]
+    def _wrap_list(self, source, path):
+        return [ self._wrap_value(v, path.new_subpath(k)) for (k, v) in enumerate(source) ]
+        #self._wrap_value(v, path.new_subpath()) for v in source ]
 
-    def _wrap_dict(self, source):
-        return { k: self._wrap_value(v) for k, v in source.iteritems() }
+    def _wrap_dict(self, source, path):
+        return { k: self._wrap_value(v, path.new_subpath(k)) for k, v in source.iteritems() }
 
-    def _update_value(self, cur, new, path):
+    def _update_value(self, cur, new):
         if isinstance(cur, Value):
             values = ValueList(cur, self._settings)
         elif isinstance(cur, ValueList):
@@ -161,7 +173,7 @@
         elif isinstance(new, dict) and isinstance(cur, dict):
             return self._merge_dict(cur, new, path)
         else:
-            return self._update_value(cur, new, path)
+            return self._update_value(cur, new)
 
     def merge(self, other):
         """Merge function (public edition).
@@ -179,9 +191,9 @@
 
         self._unrendered = None
         if isinstance(other, dict):
-            wrapped = self._wrap_dict(other)
+            wrapped = self._wrap_dict(other, DictPath(self._settings.delimiter))
         elif isinstance(other, self.__class__):
-            wrapped = self._wrap_dict(other._base)
+            wrapped = self._wrap_dict(other._base, DictPath(self._settings.delimiter))
         else:
             raise TypeError('Cannot merge %s objects into %s' % (type(other),
                             self.__class__.__name__))
@@ -190,9 +202,12 @@
     def _render_simple_container(self, container, key, value, path):
             if isinstance(value, ValueList):
                 if value.is_complex():
-                    self._unrendered[path.new_subpath(key)] = True
+                    p = path.new_subpath(key)
+                    self._unrendered[p] = True
                     if value.has_inv_query():
-                        self._has_inv_query = True
+                        self._inv_queries.append((p, value))
+                        if value.needs_all_envs():
+                            self._needs_all_envs = True
                     return
                 else:
                     value = value.merge()
@@ -206,9 +221,12 @@
                 container[key] = value
             elif isinstance(value, Value):
                 if value.is_complex():
-                    self._unrendered[path.new_subpath(key)] = True
+                    p = path.new_subpath(key)
+                    self._unrendered[p] = True
                     if value.has_inv_query():
-                        self._has_inv_query = True
+                        self._inv_queries.append((p, value))
+                        if value.needs_all_envs():
+                            self._needs_all_envs = True
                 else:
                     container[key] = value.render(None, None)
 
@@ -236,7 +254,8 @@
     def _initialise_interpolate(self):
         if self._unrendered is None:
             self._unrendered = {}
-            self._has_inv_query = False
+            self._inv_queries = []
+            self._needs_all_envs = False
             self._render_simple_dict(self._base, DictPath(self._settings.delimiter))
 
     def _interpolate_inner(self, path, inventory):
@@ -258,7 +277,7 @@
             new = value.render(self._base, inventory)
         except ResolveError as e:
             e.context = path
-            raise e
+            raise
 
         if isinstance(new, dict):
             self._render_simple_dict(new, path)
@@ -299,4 +318,4 @@
                 old = len(value.get_references())
                 value.assembleRefs(self._base)
                 if old == len(value.get_references()):
-                    raise InterpolationError('Bad references: {0}, for path: {1}'.format(value.get_references(), str(path)))
+                    raise BadReferencesError(value.get_references(), str(path))
diff --git a/reclass/datatypes/tests/test_parameters.py b/reclass/datatypes/tests/test_parameters.py
index a56ba65..4dec420 100644
--- a/reclass/datatypes/tests/test_parameters.py
+++ b/reclass/datatypes/tests/test_parameters.py
@@ -257,7 +257,7 @@
         self.assertEqual(p.as_dict()['foo'], v)
 
     def test_interpolate_list(self):
-        l = [41,42,43]
+        l = [41, 42, 43]
         d = {'foo': 'bar'.join(SETTINGS.reference_sentinels),
              'bar': l}
         p = Parameters(d, SETTINGS, '')
@@ -498,7 +498,7 @@
         p1 = Parameters({'alpha': {'one': 1, 'two': 2}, 'gamma': '${alpha:${beta}}'}, SETTINGS, '')
         with self.assertRaises(InterpolationError) as error:
             p1.interpolate()
-        self.assertEqual(error.exception.message, "Bad references: ['beta'], for path: gamma")
+        self.assertEqual(error.exception.message, "=> \n   Bad references: ${beta} for path: gamma")
 
 if __name__ == '__main__':
     unittest.main()
diff --git a/reclass/defaults.py b/reclass/defaults.py
index baac195..7fcb2a0 100644
--- a/reclass/defaults.py
+++ b/reclass/defaults.py
@@ -40,3 +40,5 @@
 IGNORE_CLASS_NOT_FOUND = False
 
 DEFAULT_ENVIRONMENT = 'base'
+INVENTORY_IGNORE_FAILED_NODE = False
+INVENTORY_IGNORE_FAILED_RENDER = False
diff --git a/reclass/errors.py b/reclass/errors.py
index d753306..a27919b 100644
--- a/reclass/errors.py
+++ b/reclass/errors.py
@@ -10,7 +10,7 @@
 import posix, sys
 import traceback
 
-from reclass.defaults import REFERENCE_SENTINELS
+from reclass.defaults import REFERENCE_SENTINELS, EXPORT_SENTINELS
 
 class ReclassException(Exception):
 
@@ -18,7 +18,8 @@
         super(ReclassException, self).__init__()
         self._rc = rc
         self._msg = msg
-        self._traceback = traceback.format_exc()
+        self._previous_traceback = traceback.format_exc()
+        self._full_traceback = False
 
     message = property(lambda self: self._get_message())
     rc = property(lambda self: self._rc)
@@ -33,8 +34,14 @@
             return 'No error message provided.'
 
     def exit_with_message(self, out=sys.stderr):
-        if self._traceback:
-            print >>out, self._traceback
+        if self._full_traceback:
+            t, v, tb = sys.exc_info()
+            print >>out, 'Full Traceback:'
+            for l in traceback.format_tb(tb):
+                print >>out, l,
+            print >>out
+        if self._previous_traceback:
+            print >>out, self._previous_traceback
         print >>out, self.message
         print >>out
         sys.exit(self.rc)
@@ -125,44 +132,74 @@
 
 class InterpolationError(ReclassException):
 
-    def __init__(self, msg, rc=posix.EX_DATAERR):
+    def __init__(self, msg, rc=posix.EX_DATAERR, nodename=''):
         super(InterpolationError, self).__init__(rc=rc, msg=msg)
-
-
-class ResolveError(InterpolationError):
-
-    def __init__(self, var, uri=None, export=None, context=None):
-        super(ResolveError, self).__init__(msg=None)
-        self.var = var
-        self.context = context
-        self.uri = uri
-        self.export = export
+        self.nodename = nodename
+        self.uri = None
+        self.context = None
 
     def _get_message(self):
+        msg = '=> {0}\n'.format(self.nodename)
+        msg += self._render_error_message(self._get_error_message(), 1)
+        msg = msg[:-1]
+        return msg
+
+    def _render_error_message(self, message_list, indent):
         msg = ''
-        if self.export:
-            msg = '** InvQuery: %s **\n' % self.export
-        msg += "Cannot resolve " + self.var.join(REFERENCE_SENTINELS)
+        for l in message_list:
+            if isinstance(l, list):
+                msg += self._render_error_message(l, indent + 1)
+            else:
+                msg += (' ' * indent * 3) + l + '\n'
+        return msg
+
+    def _add_context_and_uri(self):
+        msg = ''
         if self.context:
             msg += ', at %s' % self.context
         if self.uri:
             msg += ', in %s' % self.uri
         return msg
 
-    def set_context(self, context):
-        self._context = context
+
+class ResolveError(InterpolationError):
+
+    def __init__(self, reference, uri=None, context=None):
+        super(ResolveError, self).__init__(msg=None)
+        self.reference = reference
+
+    def _get_error_message(self):
+        msg = 'Cannot resolve {0}'.format(self.reference.join(REFERENCE_SENTINELS)) + self._add_context_and_uri()
+        return [ msg ]
 
 
-class IncompleteInterpolationError(InterpolationError):
+class InvQueryError(InterpolationError):
 
-    def __init__(self, string, end_sentinel):
-        super(IncompleteInterpolationError, self).__init__(msg=None)
-        self._ref = string.join(REFERENCE_SENTINELS)
-        self._end_sentinel = end_sentinel
+    def __init__(self, query, resolveError, uri=None, context = None):
+        super(InvQueryError, self).__init__(msg=None)
+        self.query = query
+        self.resolveError = resolveError
+        self._traceback = self.resolveError._traceback
 
-    def _get_message(self):
-        msg = "Missing '{0}' to end reference: {1}"
-        return msg.format(self._end_sentinel, self._ref)
+    def _get_error_message(self):
+        msg1 = 'Failed inv query {0}'.format(self.query.join(EXPORT_SENTINELS)) + self._add_context_and_uri()
+        msg2 = [ '--> {0}'.format(self.resolveError.nodename) ]
+        msg2.extend(self.resolveError._get_error_message())
+        return [ msg1, msg2 ]
+
+
+class ParseError(InterpolationError):
+
+    def __init__(self, msg, line, col, lineno, rc=posix.EX_DATAERR):
+        super(ParseError, self).__init__(rc=rc, msg=None)
+        self._err = msg
+        self._line = line
+        self._col = col
+        self._lineno = lineno
+
+    def _get_error_message(self):
+        msg = [ 'Parse error: {0}'.format(self._line.join(EXPORT_SENTINELS)) + self._add_context_and_uri() ]
+        msg.append('{0} at char {1}'.format(self._err, self._col - 1))
 
 
 class InfiniteRecursionError(InterpolationError):
@@ -172,9 +209,32 @@
         self._path = path
         self._ref = ref.join(REFERENCE_SENTINELS)
 
-    def _get_message(self):
+    def _get_error_message(self):
         msg = "Infinite recursion while resolving {0} at {1}"
-        return msg.format(self._ref, self._path)
+        return [ msg.format(self._ref, self._path) ]
+
+
+class BadReferencesError(InterpolationError):
+
+    def __init__(self, refs, path):
+        super(BadReferencesError, self).__init__(msg=None)
+        self._path = path
+        self._refs = [ r.join(REFERENCE_SENTINELS) for r in refs ]
+
+    def _get_error_message(self):
+        msg = 'Bad references: {0} for path: {1}'
+        return [ msg.format(", ".join(self._refs), self._path) ]
+
+
+class ExpressionError(InterpolationError):
+
+    def __init__(self, msg, rc=posix.EX_DATAERR):
+        super(ExpressionError, self).__init__(rc=rc, msg=None)
+        self._error_msg = msg
+
+    def _get_error_message(self):
+        msg = [ 'Expression error: {0}'.format(self._error_msg) + self._add_context_and_uri() ]
+        return msg
 
 
 class MappingError(ReclassException):
@@ -220,22 +280,3 @@
               "definition in '{3}'. Nodes can only be defined once " \
               "per inventory."
         return msg.format(self._storage, self._name, self._uris[1], self._uris[0])
-
-
-class ParseError(ReclassException):
-
-    def __init__(self, msg, line, col, lineno, rc=posix.EX_DATAERR):
-        super(ParseError, self).__init__(rc=rc, msg=None)
-        self._err = msg
-        self._line = line
-        self._col = col
-        self._lineno = lineno
-
-    def _get_message(self):
-        msg = "Parse error: {0} : {1} at char {2}"
-        return msg.format(self._line, self._err, self._col - 1)
-
-class ExpressionError(ReclassException):
-
-    def __init__(self, msg, rc=posix.EX_DATAERR):
-        super(ExpressionError, self).__init__(rc=rc, msg=msg)
diff --git a/reclass/settings.py b/reclass/settings.py
index 4b5928f..d0332d0 100644
--- a/reclass/settings.py
+++ b/reclass/settings.py
@@ -14,6 +14,8 @@
         self.dict_key_override_prefix = options.get('dict_key_override_prefix', reclass.defaults.PARAMETER_DICT_KEY_OVERRIDE_PREFIX)
         self.escape_character = options.get('escape_character', reclass.defaults.ESCAPE_CHARACTER)
         self.export_sentinels = options.get('export_sentinels', reclass.defaults.EXPORT_SENTINELS)
+        self.inventory_ignore_failed_node = options.get('inventory_ignore_failed_node', reclass.defaults.INVENTORY_IGNORE_FAILED_NODE)
+        self.inventory_ignore_failed_render = options.get('inventory_ignore_failed_render', reclass.defaults.INVENTORY_IGNORE_FAILED_RENDER)
         self.reference_sentinels = options.get('reference_sentinels', reclass.defaults.REFERENCE_SENTINELS)
 
         self.ref_parser = reclass.values.parser_funcs.get_ref_parser(self.escape_character, self.reference_sentinels, self.export_sentinels)
diff --git a/reclass/utils/dictpath.py b/reclass/utils/dictpath.py
index 0d23c96..1466a5e 100644
--- a/reclass/utils/dictpath.py
+++ b/reclass/utils/dictpath.py
@@ -134,6 +134,9 @@
         del self._parts[0]
         return self
 
+    def delete(self, base):
+        del self._get_innermost_container(base)[self._get_key()]
+
     def exists_in(self, container):
         item = container
         for i in self._parts:
diff --git a/reclass/values/invitem.py b/reclass/values/invitem.py
index 024ef99..cb55fc3 100644
--- a/reclass/values/invitem.py
+++ b/reclass/values/invitem.py
@@ -16,6 +16,7 @@
 _TEST = 'TEST'
 _LIST_TEST = 'LIST_TEST'
 _LOGICAL = 'LOGICAL'
+_OPTION = 'OPTION'
 
 _VALUE = 'VALUE'
 _IF = 'IF'
@@ -25,6 +26,8 @@
 _EQUAL = '=='
 _NOT_EQUAL = '!='
 
+_IGNORE_ERRORS = '+IgnoreErrors'
+_ALL_ENVS = '+AllEnvs'
 
 class Element(object):
 
@@ -35,7 +38,13 @@
         self._parameter_value = None
         self._export_path, self._parameter_path, self._parameter_value = self._get_vars(expression[0][1], self._export_path, self._parameter_path, self._parameter_value)
         self._export_path, self._parameter_path, self._parameter_value = self._get_vars(expression[2][1], self._export_path, self._parameter_path, self._parameter_value)
-        self._export_path.drop_first()
+
+        try:
+            self._export_path.drop_first()
+        except AttributeError:
+            raise ExpressionError('No export')
+
+        self._inv_refs = [ self._export_path ]
         self._test = expression[1][1]
 
         if self._parameter_path is not None:
@@ -47,12 +56,15 @@
     def refs(self):
         return self._refs
 
+    def inv_refs(self):
+        return self._inv_refs
+
     def value(self, context, items):
         if self._parameter_path is not None:
             self._parameter_value = self._resolve(self._parameter_path, context)
 
-        if self._export_path is None or self._parameter_value is None or self._test is None:
-            ExpressionError('Failed to render %s' % str(self))
+        if self._parameter_value is None or self._test is None:
+            raise ExpressionError('Failed to render %s' % str(self))
 
         if self._export_path.exists_in(items):
             result = False
@@ -100,11 +112,13 @@
         self._operators = []
         self._delimiter = delimiter
         self._refs = []
+        self._inv_refs = []
         i = 0
         while i < len(expression):
             e = Element(expression[i:], self._delimiter)
             self._elements.append(e)
             self._refs.extend(e.refs())
+            self._inv_refs.extend(e.inv_refs())
             i += 3
             if i < len(expression):
                 self._operators.append(expression[i][1])
@@ -113,6 +127,9 @@
     def refs(self):
         return self._refs
 
+    def inv_refs(self):
+        return self._inv_refs
+
     def value(self, context, items):
         if len(self._elements) == 0:
             return True
@@ -153,6 +170,10 @@
                 token = tokens[0]
             tokens[0] = (_OBJ, token)
 
+        def _option(string, location, tokens):
+            token = tokens[0]
+            tokens[0] = (_OPTION, token)
+
         def _test(string, location, tokens):
             token = tokens[0]
             tokens[0] = (_TEST, token)
@@ -179,6 +200,10 @@
 
         white_space = pp.White().suppress()
         end = pp.StringEnd()
+        ignore_errors = pp.CaselessLiteral(_IGNORE_ERRORS)
+        all_envs = pp.CaselessLiteral(_ALL_ENVS)
+        option = (ignore_errors | all_envs).setParseAction(_option)
+        options = pp.Group(pp.ZeroOrMore(option + white_space))
         operator_test = (pp.Literal(_EQUAL) | pp.Literal(_NOT_EQUAL)).setParseAction(_test)
         operator_logical = (pp.CaselessLiteral(_AND) | pp.CaselessLiteral(_OR)).setParseAction(_logical)
         begin_if = pp.CaselessLiteral(_IF, ).setParseAction(_if)
@@ -191,15 +216,19 @@
         expr_var = pp.Group(obj + pp.Optional(white_space) + end).setParseAction(_expr_var)
         expr_test = pp.Group(obj + white_space + begin_if + single_test + pp.ZeroOrMore(additional_test) + end).setParseAction(_expr_test)
         expr_list_test = pp.Group(begin_if + single_test + pp.ZeroOrMore(additional_test) + end).setParseAction(_expr_list_test)
-        expr = pp.Optional(white_space) + (expr_test | expr_var | expr_list_test)
-        return expr
+        expr = (expr_test | expr_var | expr_list_test)
+        line = options + expr + end
+        return line
 
     _parser = _get_parser()
 
     def __init__(self, item, settings):
         self.type = Item.INV_QUERY
         self._settings = settings
-        self._parse_expression(item.render(None, None))
+        self._needs_all_envs = False
+        self._ignore_failed_render = self._settings.inventory_ignore_failed_render
+        self._expr_text = item.render(None, None)
+        self._parse_expression(self._expr_text)
 
     def _parse_expression(self, expr):
         try:
@@ -210,21 +239,33 @@
         if len(tokens) == 1:
             self._expr_type = tokens[0][0]
             self._expr = list(tokens[0][1])
+        elif len(tokens) == 2:
+            for opt in tokens[0]:
+                if opt[1] == _IGNORE_ERRORS:
+                    self._ignore_failed_render = True
+                elif opt[1] == _ALL_ENVS:
+                    self._needs_all_envs = True
+            self._expr_type = tokens[1][0]
+            self._expr = list(tokens[1][1])
         else:
-            raise ExpressionError('Failed to parse %s' % str(self._expr))
+            raise ExpressionError('Failed to parse %s' % str(tokens))
 
         if self._expr_type == _VALUE:
             self._value_path = DictPath(self._settings.delimiter, self._expr[0][1]).drop_first()
             self._question = Question([], self._settings.delimiter)
             self._refs = []
+            self._inv_refs = [ self._value_path ]
         elif self._expr_type == _TEST:
             self._value_path = DictPath(self._settings.delimiter, self._expr[0][1]).drop_first()
             self._question = Question(self._expr[2:], self._settings.delimiter)
             self._refs = self._question.refs()
+            self._inv_refs = self._question.inv_refs()
+            self._inv_refs.append(self._value_path)
         elif self._expr_type == _LIST_TEST:
             self._value_path = None
             self._question = Question(self._expr[1:], self._settings.delimiter)
             self._refs = self._question.refs()
+            self._inv_refs = self._question.inv_refs()
         else:
             raise ExpressionError('Unknown expression type: %s' % self._expr_type)
 
@@ -232,7 +273,7 @@
         return
 
     def contents(self):
-        return self._expr
+        return self._expr_text
 
     def has_inv_query(self):
         return True
@@ -243,6 +284,15 @@
     def get_references(self):
         return self._question.refs()
 
+    def get_inv_references(self):
+        return self._inv_refs
+
+    def needs_all_envs(self):
+        return self._needs_all_envs
+
+    def ignore_failed_render(self):
+        return self._ignore_failed_render
+
     def _resolve(self, path, dictionary):
         try:
             return path.get_value(dictionary)
diff --git a/reclass/values/parser.py b/reclass/values/parser.py
index 1b0ba4b..bdd881d 100644
--- a/reclass/values/parser.py
+++ b/reclass/values/parser.py
@@ -26,7 +26,7 @@
             # speed up: try a simple reference
             try:
                 tokens = self._settings.simple_ref_parser.leaveWhitespace().parseString(value).asList()
-            except pp.ParseException as e:
+            except pp.ParseException:
                 # fall back on the full parser
                 try:
                     tokens = self._settings.ref_parser.leaveWhitespace().parseString(value).asList()
diff --git a/reclass/values/tests/test_value.py b/reclass/values/tests/test_value.py
index 51425cc..84403d3 100644
--- a/reclass/values/tests/test_value.py
+++ b/reclass/values/tests/test_value.py
@@ -11,8 +11,7 @@
 
 from reclass.settings import Settings
 from reclass.values.value import Value
-from reclass.errors import ResolveError, \
-        IncompleteInterpolationError, ParseError
+from reclass.errors import ResolveError, ParseError
 import unittest
 
 SETTINGS = Settings()
diff --git a/reclass/values/value.py b/reclass/values/value.py
index 23401fb..cbd5ce2 100644
--- a/reclass/values/value.py
+++ b/reclass/values/value.py
@@ -8,7 +8,7 @@
 from dictitem import DictItem
 from listitem import ListItem
 from scaitem import ScaItem
-from reclass.errors import ResolveError
+from reclass.errors import InterpolationError
 
 class Value(object):
 
@@ -18,7 +18,11 @@
         self._settings = settings
         self._uri = uri
         if isinstance(value, str):
-            self._item = self._parser.parse(value, self._settings)
+            try:
+                self._item = self._parser.parse(value, self._settings)
+            except InterpolationError as e:
+                e.uri = self._uri
+                raise
         elif isinstance(value, list):
             self._item = ListItem(value, self._settings)
         elif isinstance(value, dict):
@@ -26,6 +30,9 @@
         else:
             self._item = ScaItem(value, self._settings)
 
+    def uri(self):
+        return self._uri
+
     def is_container(self):
         return self._item.is_container()
 
@@ -38,12 +45,24 @@
     def has_inv_query(self):
         return self._item.has_inv_query()
 
+    def needs_all_envs(self):
+        if self._item.has_inv_query():
+            return self._item.needs_all_envs()
+        else:
+            return False
+
+    def ignore_failed_render(self):
+        return self._item.ignore_failed_render()
+
     def is_complex(self):
         return self._item.is_complex()
 
     def get_references(self):
         return self._item.get_references()
 
+    def get_inv_references(self):
+        return self._item.get_inv_references()
+
     def assembleRefs(self, context):
         if self._item.has_references():
             self._item.assembleRefs(context)
@@ -51,9 +70,9 @@
     def render(self, context, inventory):
         try:
             return self._item.render(context, inventory)
-        except ResolveError as e:
+        except InterpolationError as e:
             e.uri = self._uri
-            raise e
+            raise
 
     def contents(self):
         return self._item.contents()
diff --git a/reclass/values/valuelist.py b/reclass/values/valuelist.py
index 64a7cb5..f89a0c3 100644
--- a/reclass/values/valuelist.py
+++ b/reclass/values/valuelist.py
@@ -13,7 +13,9 @@
         self._refs = []
         self._allRefs = True
         self._values = [ value ]
+        self._inv_refs = []
         self._has_inv_query = False
+        self._ignore_failed_render = False
         self._update()
 
     def append(self, value):
@@ -25,7 +27,6 @@
         self._update()
 
     def _update(self):
-        self._has_inv_query = False
         self.assembleRefs()
         self._check_for_inv_query()
 
@@ -35,6 +36,9 @@
     def has_inv_query(self):
         return self._has_inv_query
 
+    def get_inv_references(self):
+        return self._inv_refs
+
     def is_complex(self):
         return (self.has_references() | self.has_inv_query())
 
@@ -44,11 +48,20 @@
     def allRefs(self):
         return self._allRefs
 
+    def ignore_failed_render(self):
+        return self._ignore_failed_render
+
     def _check_for_inv_query(self):
         self._has_inv_query = False
+        self._ignore_failed_render = True
         for value in self._values:
             if value.has_inv_query():
+                self._inv_refs.extend(value.get_inv_references)
                 self._has_inv_query = True
+                if vale.ignore_failed_render() is False:
+                    self._ignore_failed_render = False
+        if self._has_inv_query is False:
+            self._ignore_failed_render = False
 
     def assembleRefs(self, context={}):
         self._refs = []