# Buggy code
def expand_variable_dicts(list_of_variable_dicts):
    # type: (List[Union[Dataset, Dict]]) -> List[Dict[Any, Variable]]
    """Given a list of dicts with xarray object values, expand the values.

    Parameters
    ----------
    list_of_variable_dicts : list of dict or Dataset objects
        The each value for the mappings must be of the following types:
        - an xarray.Variable
        - a tuple `(dims, data[, attrs[, encoding]])` that can be converted in
          an xarray.Variable
        - or an xarray.DataArray

    Returns
    -------
    A list of ordered dictionaries with all values given by those found on the
    original dictionaries or coordinates, all of which are xarray.Variable
    objects.
    """
    var_dicts = []

    for variables in list_of_variable_dicts:
        if hasattr(variables, "variables"):  # duck-type Dataset
            sanitized_vars = variables.variables
        else:
            # append sanitized_vars before filling it up because we want coords
            # to appear afterwards
            sanitized_vars = OrderedDict()

            for name, var in variables.items():
                if hasattr(var, "_coords"):  # duck-type DataArray
                    # use private API for speed
                    coords = var._coords.copy()
                    # explicitly overwritten variables should take precedence
                    coords.pop(name, None)
                    var_dicts.append(coords)

                var = as_variable(var, name=name)
                sanitized_vars[name] = var

        var_dicts.append(sanitized_vars)

    return var_dicts


# Traceback (InvalidIndexError)
InvalidIndexError                         Traceback (most recent call last)
<ipython-input-5-50e97aa6cb4e> in <module>()
4 ds = xarray.Dataset({'data': (['dim0', 'dim1'], np.empty((5,10)))},
5                     coords={'dim0': [0, 1, 2, 0, 1], 'dim1': list(range(10))})
----> 6 ds['dim0'] = list(range(5))

/home/rotis/anaconda/envs/calphadpy3/lib/python3.5/site-packages/xarray/core/dataset.py in __setitem__(self, key, value)
536             raise NotImplementedError('cannot yet use a dictionary as a key '
537                                       'to set Dataset values')
--> 538         self.update({key: value})
539
540     def __delitem__(self, key):

/home/rotis/anaconda/envs/calphadpy3/lib/python3.5/site-packages/xarray/core/dataset.py in update(self, other, inplace)
1434             dataset.
1435         """
-> 1436         variables, coord_names, dims = dataset_update_method(self, other)
1437
1438         return self._replace_vars_and_dims(variables, coord_names, dims,

/home/rotis/anaconda/envs/calphadpy3/lib/python3.5/site-packages/xarray/core/merge.py in dataset_update_method(dataset, other)
490     priority_arg = 1
491     indexes = dataset.indexes
--> 492     return merge_core(objs, priority_arg=priority_arg, indexes=indexes)

/home/rotis/anaconda/envs/calphadpy3/lib/python3.5/site-packages/xarray/core/merge.py in merge_core(objs, compat, join, priority_arg, explicit_coords, indexes)
371
372     coerced = coerce_pandas_values(objs)
--> 373     aligned = deep_align(coerced, join=join, copy=False, indexes=indexes)
374     expanded = expand_variable_dicts(aligned)
375

/home/rotis/anaconda/envs/calphadpy3/lib/python3.5/site-packages/xarray/core/alignment.py in deep_align(list_of_variable_maps, join, copy, indexes)
146             out.append(variables)
147
--> 148     aligned = partial_align(*targets, join=join, copy=copy, indexes=indexes)
149
150     for key, aligned_obj in zip(keys, aligned):

/home/rotis/anaconda/envs/calphadpy3/lib/python3.5/site-packages/xarray/core/alignment.py in partial_align(*objects, **kwargs)
109         valid_indexers = dict((k, v) for k, v in joined_indexes.items()
110                               if k in obj.dims)
--> 111         result.append(obj.reindex(copy=copy, **valid_indexers))
112     return tuple(result)
113

/home/rotis/anaconda/envs/calphadpy3/lib/python3.5/site-packages/xarray/core/dataset.py in reindex(self, indexers, method, tolerance, copy, **kw_indexers)
1216
1217         variables = alignment.reindex_variables(
-> 1218             self.variables, self.indexes, indexers, method, tolerance, copy=copy)
1219         return self._replace_vars_and_dims(variables)
1220

/home/rotis/anaconda/envs/calphadpy3/lib/python3.5/site-packages/xarray/core/alignment.py in reindex_variables(variables, indexes, indexers, method, tolerance, copy)
218             target = utils.safe_cast_to_index(indexers[name])
219             indexer = index.get_indexer(target, method=method,
--> 220                                         **get_indexer_kwargs)
221
222             to_shape[name] = len(target)

/home/rotis/anaconda/envs/calphadpy3/lib/python3.5/site-packages/pandas/indexes/base.py in get_indexer(self, target, method, limit, tolerance)
2011
2012         if not self.is_unique:
-> 2013             raise InvalidIndexError('Reindexing only valid with uniquely'
2014                                     ' valued Index objects')
2015

InvalidIndexError: Reindexing only valid with uniquely valued Index objects

# Fixed code
def expand_variable_dicts(list_of_variable_dicts):
    # type: (List[Union[Dataset, Dict]]) -> List[Dict[Any, Variable]]
    """Given a list of dicts with xarray object values, expand the values.

    Parameters
    ----------
    list_of_variable_dicts : list of dict or Dataset objects
        The each value for the mappings must be of the following types:
        - an xarray.Variable
        - a tuple `(dims, data[, attrs[, encoding]])` that can be converted in
          an xarray.Variable
        - or an xarray.DataArray

    Returns
    -------
    A list of ordered dictionaries corresponding to inputs, or coordinates from
    an input's values. The values of each ordered dictionary are all
    xarray.Variable objects.
    """
    var_dicts = []

    for variables in list_of_variable_dicts:
        if hasattr(variables, "variables"):  # duck-type Dataset
            sanitized_vars = variables.variables
        else:
            # append coords to var_dicts before appending sanitized_vars,
            # because we want coords to appear first
            sanitized_vars = OrderedDict()

            for name, var in variables.items():
                if hasattr(var, "_coords"):  # duck-type DataArray
                    # use private API for speed
                    coords = var._coords.copy()
                    # explicitly overwritten variables should take precedence
                    coords.pop(name, None)
                    var_dicts.append(coords)

                var = as_variable(var, name=name)
                sanitized_vars[name] = var

        var_dicts.append(sanitized_vars)

    return var_dicts