# Buggy code
def decode(self, variable, name=None):
    dims, data, attrs, encoding = unpack_for_decoding(variable)

    if "missing_value" in attrs:
        # missing_value is deprecated, but we still want to support it as
        # an alias for _FillValue.
        if "_FillValue" in attrs and not utils.equivalent(
            attrs["_FillValue"], attrs["missing_value"]
        ):
            raise ValueError(
                "Conflicting _FillValue and missing_value "
                "attrs on a variable {!r}: {} vs. {}\n\n"
                "Consider opening the offending dataset "
                "using decode_cf=False, correcting the "
                "attrs and decoding explicitly using "
                "xarray.decode_cf().".format(
                    name, attrs["_FillValue"], attrs["missing_value"]
                )
            )
        attrs["_FillValue"] = attrs.pop("missing_value")

    if "_FillValue" in attrs:
        raw_fill_value = pop_to(attrs, encoding, "_FillValue", name=name)
        encoded_fill_values = [
            fv for fv in np.ravel(raw_fill_value) if not pd.isnull(fv)
        ]

        if len(encoded_fill_values) > 1:
            warnings.warn(
                "variable {!r} has multiple fill values {}, "
                "decoding all values to NaN.".format(name, encoded_fill_values),
                SerializationWarning,
                stacklevel=3,
            )

        dtype, decoded_fill_value = dtypes.maybe_promote(data.dtype)

        if encoded_fill_values:
            transform = partial(
                _apply_mask,
                encoded_fill_values=encoded_fill_values,
                decoded_fill_value=decoded_fill_value,
            )
            data = lazy_elemwise_func(data, transform, dtype)

    return Variable(dims, data, attrs, encoding)


# Traceback (UnboundLocalError)
---------------------------------------------------------------------------
UnboundLocalError                         Traceback (most recent call last)
<ipython-input-26-2052b95f2d95> in <module>()
----> 1 no2 = xr.open_dataset(product, group='/PRODUCT')

/Users/stefano/anaconda/lib/python3.6/site-packages/xarray/backends/api.py in open_dataset(filename_or_obj, group, decode_cf, mask_and_scale, decode_times, autoclose, concat_characters, decode_coords, engine, chunks, lock, cache, drop_variables)
303             lock = _default_lock(filename_or_obj, engine)
304         with close_on_error(store):
--> 305             return maybe_decode_store(store, lock)
306     else:
307         if engine is not None and engine != 'scipy':

/Users/stefano/anaconda/lib/python3.6/site-packages/xarray/backends/api.py in maybe_decode_store(store, lock)
223             store, mask_and_scale=mask_and_scale, decode_times=decode_times,
224             concat_characters=concat_characters, decode_coords=decode_coords,
--> 225             drop_variables=drop_variables)
226
227         _protect_dataset_variables_inplace(ds, cache)

/Users/stefano/anaconda/lib/python3.6/site-packages/xarray/conventions.py in decode_cf(obj, concat_characters, mask_and_scale, decode_times, decode_coords, drop_variables)
1153     vars, attrs, coord_names = decode_cf_variables(
1154         vars, attrs, concat_characters, mask_and_scale, decode_times,
-> 1155         decode_coords, drop_variables=drop_variables)
1156     ds = Dataset(vars, attrs=attrs)
1157     ds = ds.set_coords(coord_names.union(extra_coords).intersection(vars))

/Users/stefano/anaconda/lib/python3.6/site-packages/xarray/conventions.py in decode_cf_variables(variables, attributes, concat_characters, mask_and_scale, decode_times, decode_coords, drop_variables)
1086             k, v, concat_characters=concat_characters,
1087             mask_and_scale=mask_and_scale, decode_times=decode_times,
-> 1088             stack_char_dim=stack_char_dim)
1089         if decode_coords:
1090             var_attrs = new_vars[k].attrs

/Users/stefano/anaconda/lib/python3.6/site-packages/xarray/conventions.py in decode_cf_variable(name, var, concat_characters, mask_and_scale, decode_times, decode_endianness, stack_char_dim)
998         if (has_fill or scale_factor is not None or add_offset is not None):
999             if has_fill and np.array(fill_value).dtype.kind in ['U', 'S', 'O']:
-> 1000                 if string_encoding is not None:
1001                     raise NotImplementedError(
1002                         'variable %r has a _FillValue specified, but '

UnboundLocalError: local variable 'string_encoding' referenced before assignment

# Fixed code
def decode(self, variable, name=None):
    dims, data, attrs, encoding = unpack_for_decoding(variable)

    if "missing_value" in attrs:
        # missing_value is deprecated, but we still want to support it as
        # an alias for _FillValue.
        if "_FillValue" in attrs and not utils.equivalent(
            attrs["_FillValue"], attrs["missing_value"]
        ):
            raise ValueError(
                "Conflicting _FillValue and missing_value "
                "attrs on a variable {!r}: {} vs. {}\n\n"
                "Consider opening the offending dataset "
                "using decode_cf=False, correcting the "
                "attrs and decoding explicitly using "
                "xarray.decode_cf().".format(
                    name, attrs["_FillValue"], attrs["missing_value"]
                )
            )
        attrs["_FillValue"] = attrs.pop("missing_value")

    if "_FillValue" in attrs:
        raw_fill_value = pop_to(attrs, encoding, "_FillValue", name=name)
        encoded_fill_values = [
            fv for fv in np.ravel(raw_fill_value) if not pd.isnull(fv)
        ]

        if len(encoded_fill_values) > 1:
            warnings.warn(
                "variable {!r} has multiple fill values {}, "
                "decoding all values to NaN.".format(name, encoded_fill_values),
                SerializationWarning,
                stacklevel=3,
            )

        dtype, decoded_fill_value = dtypes.maybe_promote(data.dtype)

        if encoded_fill_values:
            transform = partial(
                _apply_mask,
                encoded_fill_values=encoded_fill_values,
                decoded_fill_value=decoded_fill_value,
                dtype=dtype,
            )
            data = lazy_elemwise_func(data, transform, dtype)

    return Variable(dims, data, attrs, encoding)